一文速通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)]
相关推荐
萌萌哒草头将军几秒前
⚡⚡⚡Rstack 家族即将迎来新成员 Rstest🚀🚀🚀
前端·javascript·vue.js
江城开朗的豌豆9 分钟前
Proxy:JavaScript中的'变形金刚',让你的对象为所欲为!
前端·javascript·面试
江城开朗的豌豆17 分钟前
JavaScript中的instanceof:你的代码真的认识'自家孩子'吗?
前端·javascript·面试
JinSo19 分钟前
create-easy-editor —— 快速搭建你的可视化编辑器
前端·前端框架·github
coding随想24 分钟前
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀”
javascript
Watermelo61728 分钟前
【前端实战】如何让用户回到上次阅读的位置?
前端·javascript·性能优化·数据分析·哈希算法·哈希·用户体验
Auscy36 分钟前
JavaScript 数组学习总结
开发语言·javascript·学习
zhaoyang03013 小时前
css3笔记 (1) 自用
前端·javascript·css·vue.js·笔记·html·css3
开开心心就好3 小时前
免费PDF转图片软件
javascript·智能手机·pdf·flask·word·excel·scikit-learn
珎珎啊3 小时前
CSS3 常用功能详细使用指南
前端·css·css3