提出原因:保证对象的每个属性名都是独一无二的值。 概念: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…