[关闭]
@Dale-Lin 2021-07-11T18:03:36.000000Z 字数 2687 阅读 823

ES6 symbol 和 symbol 属性d

深入理解ES6


ES6 引入新的类型 Symbol。
symbol 类型属于一种基本类型。

  1. const bar = Symbol('bar') // local symbol
  2. const foo = Symbol.for('foo') // global symbol
  3. typeof bar // 'symbol'
  4. typeof foo // 'symbol

创建Symbol

通过全局的 symbol 函数创建一个 Symbol:

  1. let firstName = Symbol();
  2. let person = {};
  3. person[firstName] = "Nicholas";
  4. console.log(person[firstName]); //"Nicholas"

第一行创建了一个名为 firstName 的 Symbol。当用其作为属性名的时候,必须通过这个 Symbol 来进行访问。

Symbol 函数接受一个描述的可选参数:

  1. let firstName = Symbol("first name");
  2. console.log(firstName); //"Symbol(first name)"

Symbol 的使用方法

所有使用可计算属性名的地方都可以使用 Symbol:

  1. let firstName = Symbol("first name");
  2. let person = {
  3. [firstName]: "Nicholas"
  4. };
  5. Object.defineProperty(person, firstName, {
  6. writable: false;
  7. });
  8. let lastName = Symbol("last name");
  9. Object.defineProperties(person, {
  10. [lastName]: {
  11. value: "Zakas",
  12. writable: false
  13. }
  14. });

Symbol 共享体系

使用 Symbol.for() 方法创建一个可共享的 Symbol:

  1. let uid = Symbol.for("uid");
  2. let obj = {};
  3. obj[uid] = "12345";
  4. console.log(obj[uid]); //"12345"
  5. console.log(uid); //"Symbol(uid)"

Symbol.for() 方法先在全局 Symbol 注册表中搜索键为 "uid" 的 Symbol 是否存在,若存在,直接返回已存在的 Symbol;否则,创建一个新的 Symbol 并注册。
后续再传入同样的键调用 Symbol.for() 会返回相同的 Symbol:

  1. let uid = Symbol.for("uid");
  2. let obj = {};
  3. obj[uid] = "12345";
  4. console.log(obj[uid]); //"12345"
  5. console.log(uid); //"Symbol(uid)"
  6. let uid2 = Symbol.for("uid");
  7. console.log(uid === uid2); //true

Symbol 属性检索

Object.keys()Object.getOwnPropertyNames() 可以检索对象中所有的属性名:前一个返回所有可枚举属性名;后一个无视枚举性全部返回。但都不支持 Symbol 属性。
ES6 添加了 Object.getOwnPropertySymbols() 方法来检索对象中的 Symbol 属性,返回包含所有 Symbol 自有属性的数组:

  1. let uid = Symbol.for("uid");
  2. let object = {
  3. [uid]: "12345"
  4. };
  5. let symbols = Object.getOwnPropertySymbols(object);
  6. console.log(symbols[length]); //1
  7. console.log(symbols[0]); //"Symbol(uid)"

通过 Symbol 操作暴露内部操作

Array.prototype.concat() 方法也可以接受多个包含数组的参数,并将数组分解成独立元素后拼接。

Symbol.isConcatSpreadable 属性是一个布尔值,如果该属性值为 true,则表示对象有 length 属性和数字键,故他的数值型属性值应该被独立添加到 concat() 调用的结果中:

  1. let collection = {
  2. 0: "Hello",
  3. 1: "world",
  4. length: 2,
  5. [Symbol.isConcatSpreadable]: true
  6. };
  7. let message = ["Hi"].concat(collection);
  8. console.log(message); //["Hi", "Hello", "world"];

也可以在派生数组子类中将 Symbol.isConcatSpreadable 设置为 false,从而防止元素在调用 concat() 时被分解。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注