Symbol

概述

ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是ES6引入Symbol的原因。

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,前六种是:Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

Symbol的特性就是唯一性

Symbol(符号)是一种新的基本类型值

基本使用

Symbol的使用就是直接圆括号调用,不能通过new来构造

基本使用

 

 Symbol内部可以传入参数,参数的作用是对这个符合的描述

let a = Symbol('hello')
console.log(a);

 

 Symbol的唯一性

Symbol是代表唯一的意思,同值的Symbol是不相等的

let a = Symbol()
let b = Symbol()
console.log(a == b); 

 

 即使内部传入参数相同也不相等

let a = Symbol('hello')
let b = Symbol('hello')
console.log(a == b); 

 

 Symbol的内部参数

(1)Symbol内部如果是字符串表示当前这个符合的描述信息

let a = Symbol('hello')
console.log(a)

(2)Symbol内部如果是对象,并且有toString方法,返回的就是这个符合的描述

let a = Symbol({
  a: 100,
  toString: function() {
      return "symbol的描述信息"
  }
})
console.log(a);

 

(3)Symbol内部如果是数组,内部的参数会被扁平化,用逗号隔开

let a = Symbol([
    1,
    2,
    'a',
    'b'
])
console.log(a);

 

 Symbol的应用场景

Symbol可以来创建对象的内部属性,内部属性的特点是防止外部获取或者随意篡改

let sym = Symbol("objKey")
let obj = {
    a: 1,
    b: 2,
    c: 3,
    [sym]: 1
}
obj.c = 2;
console.log(obj);

 

symbol定义的属性,外部是无法获取的,因为我们知道symbol同值是不相等的。所以下面的途径是获取不到的

obj[Symbol("objKey")]

上面的结果会返回undefined,因为symbol("objKey") != symbol("objKey")

 并且对象遍历symbol的时候是得不到这个key的

let sym = Symbol("objKey")
let obj = {
    a: 1,
    b: 2,
    c: 3,
    [sym]: 300
}

for (let item in obj) {
    console.log(item);
}

 使用Object.keys方法也不能获取symbol对应的key

let sym = Symbol("objKey")
let obj = {
    a: 1,
    b: 2,
    c: 3,
    [sym]: 300
}

console.log(Object.keys(obj));

 

 获取对象中Symbol的key的方法

 第一个方法是Object.getOwnPropertySymbols,返回的是只有symbol定义的key

let sym = Symbol("objKey")
let obj = {
    a: 1,
    b: 2,
    c: 3,
    [sym]: 10
}
let result = Object.getOwnPropertySymbols(obj)
console.log(result)

第二个方法是Reflect.ownKeys,返回的是所有的key,包含symbol定义的key

let sym = Symbol("objKey")
let obj = {
    a: 1,
    b: 2,
    c: 3,
    [sym]: 10
}
let result = Reflect.ownKeys(obj)
console.log(result)

 

 这两种方法还是可以获取对象中symbol对应的值的

let sym = Symbol("objKey")
let obj = {
    a: 1,
    b: 2,
    c: 3,
    [sym]: 10
}
let result = obj[Object.getOwnPropertySymbols(obj)[0]]
console.log(result)

 

 共享符号

上面注册的都是普通符号,也可以注册共享符号

 普通符号:

let a = Symbol()

共享符号:

let a = Symbol.for()

.for()就代表创建了一个共享的符号,内部参数也是描述信息

let str = Symbol.for("b");
let str2 = Symbol.for("b");
console.log(str == str2); 

 

 上面的结果返回的是true,机理是:Symbol.for()定义的符号代表共享符号,如果创建了共享符号,此时就相当于在全局创建了一个符号,此时如果再次创建相同描述的符号,就不会再创建新的了,而是将原来的抛出,所以结果是相等的。

 Symbol.keyFor方法

来获取已经注册到全局的共享符号的描述信息

let str = Symbol.for("b");
console.log(Symbol.keyFor(str));

 

 Symbol的注意事项

Symbol值不能与其他类型的值进行运算,会报错:

var str = Symbol('小明');
console.log("我是"+str)

 

 Symbol值可以显式转为字符串:

var str = Symbol('小明');
let str2=String(str)
let str3=str.toString()
console.log(typeof str2)
console.log(typeof str3)

 

 Symbol值也可以转为布尔值,但是不能转为数值

var num = Symbol(2);
let num2=Boolean(num);
console.log(typeof num2)

 

 此时改为数值就回报错

var num = Symbol(2);
let num2=Number(num);
console.log(typeof num2)

 

posted @ 2021-10-26 14:21  keyeking  阅读(636)  评论(0编辑  收藏  举报