当前位置: 首页 > news >正文

什么是Symbol?在实际开发中怎么用?

Symbol 是 ECMAScript 6(ES6)引入的一种新的基本数据类型Symbol 类型的值是唯一不可变的。目的是确保对象属性使用唯一标识符,不会发生属性冲突的危险。

1. 使用Symbol() 创建

调用 Symbol()函数时,也可以传入一个字符串参数作为对符号的描述,将来可以通过这个字符串来调试代码。但是,这个字符串参数与符号定义或标识完全无关。

	let sym1 = Symbol()let sym2 = Symbol('description')console.log(typeof sym1)//symbolconsole.log(sym1)//Symbol()console.log(sym2)//Symbol('description')const s1 = Symbol('foo')const s2 = Symbol('foo')const s3 = Symbol()const s4 = Symbol()console.log(s1 === s2);//falseconsole.log(s3 === s4);//false

注意Symbol()函数不能与 new 关键字一起作为构造函数使用,这样做是为了避免创建包装对象。Symbol 的设计初衷是为了创建唯一的标识符,而不是作为构造函数创建对象。
new Symbol()会导致 TypeError,因为 Symbol 不是构造函数。

 const s1 = new Symbol()// Uncaught TypeError: Symbol is not a constructor

2. 使用 Symbol.for()创建可共享Symbol

Symbol.for 会检查全局 Symbol 注册表,如果存在相同描述的 Symbol,则返回已存在的 Symbol;否则,创建一个新的 Symbol。什么是幂等操作?

    let s1 = Symbol.for('foo'); // 创建新的Symbollet s2 = Symbol.for('foo'); // 通过描述符在全局注册表中获取Symbolconsole.log(s1 === s2); // true

Symbol.for()每个字符串键都执行幂等操作。无论在何处调用 Symbol.for(‘foo’),都会返回相同的全局共享 Symbol。
而每次调用 Symbol() 都会创建一个新的、不共享的 Symbol。即使描述符相同,每次调用Symbol(‘foo’) 都会返回一个不同的 Symbol。

const s1 = Symbol('foo');
const s2 = Symbol('foo');
const s3 = Symbol.for('foo');console.log(s1 === s2); // false
console.log(s2 === s3); // false

3. 在实际开发中的运用

3.1 作为对象属性的键

由于 Symbol 的唯一性,它可以用作对象的属性名,且不容易被意外覆盖。

// 创建一些 Symbol 属性
const symbol1 = Symbol('symbol1');
const symbol2 = Symbol('symbol2');const obj = {[symbol1]: 'value1',[symbol2]: 'value2',
};

3.2 定义常量

使用 Symbol 可以创建全局唯一的常量,避免命名冲突

const LogLevel = {INFO: Symbol('INFO'),WARNING: Symbol('WARNING'),ERROR: Symbol('ERROR')
};function logMessage(message, level = LogLevel.INFO) {// 根据不同的日志级别执行不同的操作if (level === LogLevel.INFO) {console.log(`INFO: ${message}`);} else if (level === LogLevel.WARNING) {console.warn(`WARNING: ${message}`);} else if (level === LogLevel.ERROR) {console.error(`ERROR: ${message}`);}
}logMessage('Something happened', LogLevel.WARNING);

3.3 实现类似私有成员

通过将 Symbol 用作属性名,可以模拟实现类似私有成员的概念。

const privateProperty = Symbol('privateProperty');class MyClass {constructor() {this[privateProperty] = 'I am private!';}getPrivateProperty() {return this[privateProperty];}
}const instance = new MyClass();
console.log(instance.getPrivateProperty()); // 输出:I am private!
console.log(instance[privateProperty]); // undefined,无法直接访问私有属性

3.4 使用内置 Symbol 值

JavaScript 提供了一些内置的 Symbol 值,例如 Symbol.iteratorSymbol.toPrimitive 等,它们用于定义对象的默认迭代行为、类型转换等。
拿Symbol.iterator 举个栗子:
它是一个内置的 Symbol 值,它用于定义对象的默认迭代器
迭代器是一个对象,它实现了一个 next方法,该方法返回包含 valuedone 属性的对象,value 表示当前迭代的值,done属性表示迭代是否完成。

const myObject = {values: [1, 2, 3],[Symbol.iterator]: function () {let index = 0;const values = this.values;return {next: function () {return index < values.length ?{ value: values[index++], done: false }:{ value: undefined, done: true };}};}
};for (const value of myObject) {console.log(value);
}

4. Symbol的遍历

注意:Symbol 是不可被枚举的,因此使用 for...in循环或 Object.keys() 无法遍历出 Symbol 属性。
Object.getOwnPropertySymbols(obj),可以获取所Symbol 属性值, 返回值是一个数组。

    const symbol1 = Symbol('symbol1');const symbol2 = Symbol('symbol2');const obj = {[symbol1]: 'value1',[symbol2]: 'value2',greeting: 'hello'};// 获取对象的所有 Symbol 属性const symbolProperties = Object.getOwnPropertySymbols(obj);console.log(symbolProperties);// [Symbol(symbol1), Symbol(symbol2)]console.log(Object.keys(obj));// ['greeting']

Reflect.ownKeys(obj),可以获取包含 Symbol在内的所有键。

    // 获取包含 Symbol的所有键const allKeys = Reflect.ownKeys(obj);console.log(allKeys);//[Symbol(symbol1), Symbol(symbol2),'greeting']

同样,也可以使用Object.keysObject.getOwnPropertySymbols的组合的数组。

    const allKeys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];console.log(allKeys);

JavaScript高级知识点:
1.什么是闭包和作用域链?
2.什么是arguments对象?
3.什么是proxy代理?
4.类数组对象是什么?
5.Array.from()的6种常见用法

相关文章:

  • 软件设计师——信息安全(一)
  • java.lang.ClassNotFoundException:javax.xml.bind.DatatypeConverter 报错解决
  • 数据库原理与应用——简答题练习(数据管理技术发展、数据库主要特征、数据模型、关系模型、实体性之间的关系、DBMS的功能、相关术语解释、数据库系统)
  • arcgis api for js 中使用API的代理页面(跨越配置)
  • 【docker 】Dockerfile指令学习
  • 爬虫工作量由小到大的思维转变---<第三章 搞多大的盘>
  • c++程序设计定义一个 (图书)类,在该类定义中包括
  • 【数据结构】树状数组总结
  • 推荐一款好用的包含表格识别的OCR网站
  • Debian系统安装OpenVPN
  • javaWebssh汽车销售管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计
  • Flink系列之:窗口关联
  • HTML面试题
  • 【Spark面试】Spark面试题答案
  • 修改npm源码解决服务端渲染环境中localstorage报错read properties of undefined (reading getItem)
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • CSS 三角实现
  • HashMap剖析之内部结构
  • JavaScript 基本功--面试宝典
  • Java多线程(4):使用线程池执行定时任务
  • Java教程_软件开发基础
  • js中的正则表达式入门
  • Python3爬取英雄联盟英雄皮肤大图
  • V4L2视频输入框架概述
  • Zepto.js源码学习之二
  • 给Prometheus造假数据的方法
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 全栈开发——Linux
  • 使用Gradle第一次构建Java程序
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 小程序button引导用户授权
  • 走向全栈之MongoDB的使用
  • 昨天1024程序员节,我故意写了个死循环~
  • ​iOS安全加固方法及实现
  • #知识分享#笔记#学习方法
  • (javascript)再说document.body.scrollTop的使用问题
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • .Net - 类的介绍
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • [ MSF使用实例 ] 利用永恒之蓝(MS17-010)漏洞导致windows靶机蓝屏并获取靶机权限
  • [C++11 多线程同步] --- 条件变量的那些坑【条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)】
  • [Cloud Networking] Layer 2
  • [Design Pattern] 工厂方法模式
  • [hdu 4552] 怪盗基德的挑战书
  • [HDU3710]Battle over Cities
  • [iOS]让Xcode 4.2生成的app支持老的iOS设备(armv6)
  • [Jquery] 实现鼠标移到某个对象,在旁边显示层。
  • [JS]变量
  • [LeetCode] NO. 387 First Unique Character in a String
  • [Linux]如何理解kernel、shell、bash