一文速通es6新特性symbol

Symbol 是 JavaScript 中的一种基本数据类型,它在 ES6(ECMAScript 2015)中被引入。Symbol 类型的值是唯一的且不可改变的,这使得它们非常适合用作对象属性的键,以避免键名冲突或用于创建私有属性。

创建 Symbol

你可以通过调用 Symbol() 函数来创建一个新的 Symbol 值。每次调用 Symbol() 都会生成一个全新的、独一无二的 Symbol

javascript 复制代码
let sym1 = Symbol();
let sym2 = Symbol("description"); // 可选的描述字符串
  • 注意 :即使两个 Symbol 使用相同的描述字符串创建,它们仍然是不同的 Symbol

Symbol 的特性

唯一性

每个 Symbol 都是唯一的,即使它们有相同的描述:

javascript 复制代码
let sym3 = Symbol("foo");
let sym4 = Symbol("foo");
console.log(sym3 === sym4); // false

虽然 Symbol 的描述不会影响其唯一性,但它可以在调试时提供信息。例如,当使用 console.log 输出 Symbol 或者在错误消息中显示 Symbol 时,描述可以帮助理解 Symbol 的用途。

javascript 复制代码
console.log(Symbol("foo")); // Symbol(foo)

作为对象属性键

Symbol 最常见的用途之一是作为对象属性的键。由于 Symbol 的唯一性,可以确保不会与其他属性发生命名冲突,即使这些属性来自第三方代码库。由于每一个 Symbol 值都是不相等的,这意味着只要 Symbol 值作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。

javascript 复制代码
let obj = {};
let sym = Symbol("key");

obj[sym] = "value";
console.log(obj[sym]); // value
console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertyNames(obj)); // []
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(key)]
js 复制代码
let mySymbol = Symbol();

// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
let a = {
  [mySymbol]: 'Hello!'
};

// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果
a[mySymbol] // "Hello!"

全局符号注册表

有时你可能希望多个 Symbol 在整个应用中是共享的和可识别的。为此,JavaScript 提供了全局符号注册表,可以通过 Symbol.forSymbol.keyFor 来访问。

  • Symbol.for(key):查找已存在的 Symbol 或创建一个新的 Symbol 并将其存储在全球符号注册表中。
  • Symbol.keyFor(sym):返回给定 Symbol 的键名(如果它是在全局符号注册表中定义的)。
javascript 复制代码
let symA = Symbol.for("com.example.id");
let symB = Symbol.for("com.example.id");
console.log(symA === symB); // true

console.log(Symbol.keyFor(symA)); // com.example.id

内置符号

JavaScript 还为一些内置行为定义了特殊的 Symbol,称为"well-known symbols"。这些符号通常用于指定对象的行为,并允许开发者自定义这些行为。例如:

  • Symbol.iterator:用于定义对象的默认迭代行为。
  • Symbol.toPrimitive:用于定义对象到原始值的转换。
  • Symbol.species:用于指定构造函数应返回的构造函数。
  • Symbol.hasInstance:用于自定义 instanceof 操作符的行为。
  • 等等。

Symbol 的不可枚举性

Symbol 用作对象属性键时,默认情况下它是不可枚举的,这意味着它不会出现在 for...in 循环中,也不会出现在 Object.keys(), Object.getOwnPropertyNames() 等方法的结果中。但是,你可以使用 Object.getOwnPropertySymbols() 来获取对象的所有 Symbol 属性。

Symbol()函数创建 Symbol 值时,可以用参数添加一个描述。

ini 复制代码
const sym = Symbol('foo');

上面代码中,sym这个值的描述就是字符串foo

但是,读取这个描述需要将 Symbol 显式转为字符串,即下面的写法。

scss 复制代码
const sym = Symbol('foo');

String(sym) // "Symbol(foo)"
sym.toString() // "Symbol(foo)"

属性名的遍历

Symbol 值作为属性名,遍历对象的时候,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回。

但是,它也不是私有属性,有一个Object.getOwnPropertySymbols()方法,可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。

ini 复制代码
const obj = {};
let a = Symbol('a');
let b = Symbol('b');

obj[a] = 'Hello';
obj[b] = 'World';

const objectSymbols = Object.getOwnPropertySymbols(obj);

objectSymbols
// [Symbol(a), Symbol(b)]
ini 复制代码
const obj = {};
const foo = Symbol('foo');

obj[foo] = 'bar';

for (let i in obj) {
  console.log(i); // 无输出
}

Object.getOwnPropertyNames(obj) // []
Object.getOwnPropertySymbols(obj) // [Symbol(foo)]
相关推荐
brzhang14 分钟前
代码即图表:dbdiagram.io让数据库建模变得简单高效
前端·后端·架构
三巧25 分钟前
纯CSS吃豆人(JS仅控制进度)
javascript·css·html
SummerGao.26 分钟前
【解决】layui layer的提示框,弹出框一闪而过的问题
前端·layui
软件技术NINI42 分钟前
html css js网页制作成品——HTML+CSS+js美甲店网页设计(5页)附源码
javascript·css·html
天天扭码1 小时前
从数组到对象:JavaScript 遍历语法全解析(ES5 到 ES6 + 超详细指南)
前端·javascript·面试
拉不动的猪1 小时前
前端开发中常见的数据结构优化问题
前端·javascript·面试
街尾杂货店&1 小时前
css word
前端·css
Мартин.1 小时前
[Meachines] [Hard] CrimeStoppers LFI+ZIP-Shell+Firefox-Dec+DLINK+rootme-0.5
前端·firefox
冰镇生鲜1 小时前
快速静态界面 MDC规则约束 示范
前端
技术与健康1 小时前
【解读】Chrome 浏览器实验性功能全景
前端·chrome