ES6-Symbol

250 阅读3分钟

提出原因:保证对象的每个属性名都是独一无二的值。 概念:Symbol是ES6引入的基本类型,表示独一无二的值,在Symbol提出之前,对象的属性名只能为字符串这一种基础类型,在Symbol提出之后,对象的属性名可以有两种基础类型,即Symbol与字符串。

tips:前六种原始数据类型是:
    1:undefined(ECMA-262第3版中提出,主要是为了正式区分空对象与未经初始化的变量)
    2:null
    3:Number
    4:String
    5:Boolean
    6:Object

在了解了Symbol产生的原因,以及概念以后,再来看看要怎样创建一个Symbol吧

Symbol,创建有点特殊,他不像其他的基础类型,可以直接创建。

比如 const num = 6; const s = "string"

当然这些基础类型也可以,用const num = Number(6);const s = String("string")创建

Symbol的创建

Symbol值通过Symbol函数生成。

const symbol = Symbol();
typeof symbol    返回"symbol"
tips:这里不能用new关键字,因为symbol是一个原始类型的值,不是一个对象,如果在函数前使用new关键字,会报错

Sybom的描述

在创建Symbol的时候,我们可以传一个对Symbol的描述

类似于const s = Symbol('foo')
tips:
    1:如果传的值是对象,则调用toString方法,将对象转换为字符串,然后再生成一个Symbol值。
    2:Symbol的描述主要是为了在控制台显示,或者转为字符串时,容易区分。
    但是相同参数的Symbol函数返回的Symbol值,是不同的。若想根据参数返回同一个Symbol,可使用Symbol.for()。
    例如:
        let s1 = Symbol('foo');
        let s2 = Symbol('foo');
        s1 === s2 // false
        s1.toString() //"Symbol(foo)"
        同时,在ES2019之前,取值Symbol的描述也需通过调用toString的方法,所以,ES2019提供了一个实例属性description,直接返回Symbol的描述。
        s1.description // "foo"
    3:Symbol值,不能与其他类型的值进行运算,会报错。
    4:Symbol可以转换为字符串和布尔值
    5:Symbol不可以转换为数值

作为属性名的Symbol

可以借助Symbol的值都是不相等的特性,让Symbol值作为标识符,作为对象的属性名,就能保证,不会出现同名属性,可防止一个键不小心改写,或者覆盖。

在作为属性名时,只能通过方括号或者Object.defineProperty,Reflect.defineProperty,为对象的属性名指定一个Symbol值。

tips:
    1:不能使用点运算符,因为点运算符后面总是字符串,所以不会读取对应的symbol值,而是直接取用字符串

let mySymbol = Symbol();
// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
let a = {
    [mySymbol]: 'Hello!'
};
// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 第四种写法
Reflect.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上写法都得到同样结果
a[mySymbol] // "Hello!"

属性名的遍历

不会遍历到Symbol属性的方式

1:for...in

2:for...of

3:Object.keys()

4:Object.getOwnPropertyNames()

5:JSON.stringify()

获取Symbol属性的方式

1:Object.getOwnPropertySymbols()// 返回一个数组,成员是当前对象的所有Symbol属性值 2:Reflect.ownKeys()方法可以返回所有类型的键名,包括常规键名,和Symbol键名

Symbol.for和Symbol.keyFor()

当我们需要使用同一个Symbol值时,可以使用Symbol.for()可以做到,这个方法接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个symbol值,没有就新建一个以该字符串为名称的Symbol值,并且将其注册到全局。

Symbol.keyfor():返回一个已登记的Symbol类型值的key

let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined
因为s2并没有登记key值,所以返回undefined
注意,Symbol.for()为 Symbol 值登记的名字,是全局环境的,不管有没有在全局环境运行。

此外,还有Symbol的内置方法,此文章主要整理一下,Symbol的概念等。

更多关于Symbol的信息及,参考连接:es6.ruanyifeng.com/#docs/symbo…