ES6新增了基本数据类型Symbol,最大的特点是每个Symbol都是唯一的。(解决变量冲突问题)
let a = Symbol();
let b = Symbol();
console.log(a === b); // false
一. 使用typeof
测试类型时,返回symbol,因为symbol是基本数据类型
console.log(typeof(Symbol()));// symbol
二. 无法对Symbol()
使用new
,因为Symbol产生的是原始值,而不是包装对象,也意味着无法像对象一样添加属性。
let c = new Symbol();// TypeError: Symbol is not a constructor
三. Symbol()
接受参数,用于作为描述(方便区分不同symbol实例)
let tom = Symbol('tom');
let jack = Symbol('jack');
console.log(tom);// Symbol(tom)
console.log(jack);// Symbol(jack)
注意:参数只是描述符,与symbol的值没有关系,相同的参数不会使值相等
console.log(Symbol('a') === Symbol('a'));// false
四. 关于symbol类型转换
- symbol无法被隐式转换为string
console.log('my name is' + Symbol('tom'));
// TypeError: Cannot convert a Symbol value to a string
- 但是,symbol可以显式转换为string
console.log(Symbol('tom').toString());// Symbol(tom)
- symbol可以转换为boolean(显式转换、隐式转换都可以)
console.log(Boolean(Symbol()));// true
console.log(!Symbol());// false
- symbol无法转换为number(显式转换、隐式转换都不可以)
console.log(Symbol(1) + 1);
// TypeError: Cannot convert a Symbol value to a number
console.log(Number(Symbol(1)));
// TypeError: Cannot convert a Symbol value to a number
五. symbol的枚举
- 使用
for in
无法获取对象中的symbol属性
const name = Symbol('name');
const age = Symbol('age');
let obj = {
[name]:'tom',
[age]:21,
'hobby':'football'
};
for(let item in obj){
console.log(item,obj[item]);
}
// hobby football
-
Object.getOwnPropertyNames()
也无法获取遍历到symbol属性
console.log(Object.getOwnPropertyNames(obj));// [ 'hobby' ]
-
-
in
操作符无法判断symbol
console.log([name] in obj);
// TypeError: Cannot convert a Symbol value to a string
-
hasOwnProperty()
无法判断symbol
console.log(obj.hasOwnProperty([name]));
// TypeError: Cannot convert a Symbol value to a string
-
JSON.stringify()
转换时也会忽略symbol
console.log(JSON.stringify( { name:'tom',[Symbol('age')]:21 } ))
// {"name":"tom"}
- 正确遍历symbol的方法:
Object.getOwnPropertySymbols()
const name = Symbol('name'); const age = Symbol('age'); let obj = { [name]:'tom', [age]:21, hobby:'football' }; console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(name), Symbol(age) ]
Reflect.ownKeys()
const name = Symbol('name'); const age = Symbol('age'); let obj = { [name]:'tom', [age]:21, hobby:'football' }; console.log(Reflect.ownKeys(obj)); // [ 'hobby', Symbol(name), Symbol(age) ]
六. symbol的应用
- 作为对象的属性名,因为唯一性,symbol作为属性名能避免命名冲突(覆盖)
const name = Symbol('name');
let obj1 = {};
obj1[name] = 'tom';
let obj2 = {
[name]:'tom'
};
let obj3 = {};
Object.defineProperty(obj3,name,{
value:'tom'
});
调用对象中以symbol为属性名的属性时,只能使用[]
的方式,不能使用.
,定义属性时同理。(因为点运算符默认接字符串)
console.log(obj1.name);// undefined
console.log(obj1[name]);// tom
console.log(obj1['name']);// undefined