ES6中的Symbol ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。
重要的干货提前说:当使用JSON.stringify()
将对象转换成JSON字符串的时候,Symbol属性也会被排除在输出内容之外,所以JSON.parse(JSON.stringify(oldObj))不能拷贝含有Symbol属性的对象。另一文:JSON.parse拷贝的局限性
它是 JavaScript 语言的第七种数据类型,前六种是:undefined
、null
、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)
这样写是会报错的: let a = new Symbol() Uncaught TypeError: Symbol is not a constructor
注意:Symbol
函数前不能使用new
命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。
所以,我们只要将Symbol当成唯一的字符串就行
正确写法: let s = Symbol(); typeof s // "symbol"
1,概要:
1,每一个Symbol都不相等
// 没有参数的情况 let s1 = Symbol(); let s2 = Symbol(); s1 === s2 // false
2,Symbol能接受一个参数,注意数只是表示对当前 Symbol 值的描述,相同参数的Symbol值也都是不相同的;
参数可以为所有类型,如果 Symbol 的参数是一个对象,就会调用该对象的toString
方法
3,注意:Symbol 值不能与其他类型的值进行运算,但是,Symbol 值可以显式转为字符串,另外,Symbol 值也可以转为布尔值,但是不能转为数值。
let sym = Symbol('My symbol'); String(sym) // 'Symbol(My symbol)' let sym = Symbol(); Boolean(sym) // true Number(sym) // TypeError "your symbol is " + sym // TypeError: can't convert symbol to string
2,Symbol.prototype.description
let sym = Symbol('hello') sym //Symbol(hello) sym.description //"hello"
3,作为属性名时的遍历
Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。
但是,它也不是私有属性,有一个Object.getOwnPropertySymbols()
方法,可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
const obj = {}; let a = Symbol('a'); let b = Symbol('b'); obj[a] = 'Hello'; obj[b] = 'World';
for (let i in obj) {
console.log(i); // 无输出
}
const objectSymbols = Object.getOwnPropertySymbols(obj); objectSymbols // [Symbol(a), Symbol(b)]
另一个新的 API,Reflect.ownKeys()
方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
let obj = { [Symbol('my_key')]: 1, enum: 2, nonEnum: 3 }; Reflect.ownKeys(obj) // ["enum", "nonEnum", Symbol(my_key)]
4,Symbol.for(),Symbol.keyFor()
Symbol.for()
与Symbol()
这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会
let s1 = Symbol.for('foo'); let s2 = Symbol.for('foo'); s1 === s2 // true Symbol.for("bar") === Symbol.for("bar") // true Symbol("bar") === Symbol("bar") // false Symbol.keyFor()方法返回一个已登记的 Symbol 类型值的key。 let s1 = Symbol.for("foo"); Symbol.keyFor(s1) // "foo" let s2 = Symbol("foo"); Symbol.keyFor(s2) // undefined
Symbol.for()
的这个全局登记特性,可以用在不同的 iframe 或 service worker 中取到同一个值。
iframe = document.createElement('iframe'); iframe.src = String(window.location); document.body.appendChild(iframe); iframe.contentWindow.Symbol.for('foo') === Symbol.for('foo') // true