Symbol

221 阅读2分钟

Symbol 用于防止属性名冲突而产生的,比如向第三方对象中添加属性时。 Symbol 的值是唯一的,独一无二的不会重复的。

基础知识

Symbol

  let hd = Symbol();
  let edu = Symbol();
  console.log(hd);    // Symbol()
  console.log(hd == edu)    // false

Symbol不可以添加属性

  let hd = Symbol();
  hd.name = "test";
  console.log(hd.name)    //undefined

描述参数

可传入字符串用于描述Symbol,方便在控制台中分辨Symbol

  let hd = Symbol("is name");
  let edu = Symbol('这是一个测试');
  console.log(hd);    // Symbol(is name)
  console.log(edu)    // Symbol(这是一个测试)

传入相同参数Symbol 也是唯一独立的,因为参数只是描述而已,但使用Symbol.for则不会

let hd = Symbol("test");
let edu = Symbol('test');
console.log(hd == edu)    // false

// 使用description 可以获取传入的描述参数

let hd = Symbol("test");
console.log(hd.description)    // test

Symbol.for

根据描述获取Symbol,如果不存在则创建一个Symbol

  • 使用Symbol.for 会在系统中将Symbol登记
  • 使用Symbol 则不会登记
let hd = Symbol.for('test');
let edu = Symbol.for('test');
console.log(hd == edu)    // true

Symbol.keyFor

Symbol.keyFor 根据Symbol.for登记的Symbol返回描述,如果找不到返回undefined

 let hd = Symbol.for("test");
  console.log(Symbol.keyFor(hd))    // test

  let edu = Symbol("test");
  console.log(Symbol.keyFor(edu));    // undefined

对象属性

Symbol是独一无二的可以保证对象属性的唯一

  • Symbol 声明和访问使使用[]形式操作
  • 也不能使用. 语法 因为.语法是操作字符串属性的

下面的写法是错误的,会将symbol当成字符串symbol处理

let symbol = Symbol("test");
  let obj = {
    symbol: 'test'
  };
  console.log(obj);

正确写法是以[]变量形式声明和访问

  let symbol = Symbol("test");
  let obj = {
    [symbol]: 'test'
  };
  console.log(obj[symbol]);    // test

实例操作

使用Symbol 可以解决在保存数据时由于名称相同造成的耦合覆盖问题

缓存操作

class Cache {
  static data = {};
  static set(name, value) {
    this.data[name] = value;
  }
  static get(name) {
    return this.data[name];
  }
}

let user = {
  name: "后盾人",
  key: Symbol("缓存")
};

let cart = {
  name: "购物车",
  key: Symbol("购物车")
};

Cache.set(user.key, user);
Cache.set(cart.key, cart);
console.log(Cache.get(user.key));

遍历属性

Symbol不能使用for/in for/of 遍历操作

let symbol = Symbol("test");
let obj = {
  name: "zch",
  [symbol]: "test"
};

for (const key in obj) {
  console.log(key); //name
}

for (const key of Object.keys(obj)) {
  console.log(key); //name
}

可以使用Object.getOwnPropertySymbols获取所有的Symbol属性

...
for (const key of Object.getOwnPropertySymbols(obj)) {
  console.log(key);
}

也可以使用 Reflect.ownKeys(obj) 获取所有属性包括Symbol

...
for (const key of Reflect.ownKeys(obj)) {
  console.log(key);
}
...

如果对象属性不想被遍历可以使用Symbol保护

const site = Symbol("网站名称");
class User {
  constructor(name) {
    this[site] = "test";
    this.name = name;
  }
  getName() {
    return `${this[site]}-${this.name}`;
  }
}
const hd = new User("zch");
console.log(hd.getName());
for (const key in hd) {
  console.log(key);
}