ES6中引入了第6种原始类型:Symbol(用给定名称作为唯一标识)
一、创建Symbol
let firstName = Symbol();
let person = {};
person[firstName] = '易安';
console.log(person[firstName]); //'易安'
Symbol函数接受一个可选参数,可添加一段文本描述即将创建的Symbol,这段属描述不可用于属性访问,但建议每次创建Symbol时都添加一段描述,便于阅读代码和调试Symbol程序。
let firstName = Symbol('first name');
let person = {};
person[firstName] = '易安';
console.log('first name' in person); //false
console.log(person[firstName]); //'易安'
console.log(firstName); //Symbol('first name')
二、Symbol的辨识方法
Symbol是原始值,且ES6同时扩展了typeof操作符,支持返回“Symbol”,所以可以用typeof来检测变量是否为Symbol类型
let symbol = Symbol('test symbol');
console.log(typeof symbol); //'symbol'
三、Symbol共享体系
- 若想创建一个可共享的Symbol,要使用Symbol.for()方法。
- 它只接受一个参数,也就是即将创建的Symbol的字符串标识符,这个参数同样也被用作Symbol的描述:
let uid1 = Symbol.for('uid');
let object = {};
object[ uid1 ] = '12345';
console.log(object[uid1 ]); //12345
console.log(uid1 ); //Symbol(uid)
说明:
- Symbol.for()方法首先在全局Symbol注册表中搜索键为‘uid1’的Symbol是否存在:
- 若存在,直接返回已有的Symbol;
- 否则,创建一个新的Symbol,并使用这个键在Symbol全局注册表中注册,随机返回新创建的Symbol。
- 后续如果再传入同样的键调用Symbol.for()会返回相同的Symbol:
let uid1 = Symbol.for('uid');
let uid2 = Symbol.for('uid');
let object = {};
object[ uid1 ] = '12345';
console.log(uid1 == uid2); //true
console.log(object[uid1 ]); //12345
console.log(object[uid2]); //12345
console.log(uid1 ); //Symbol(uid)
- 使用Symbol.keyFor()方法在Symbol全局注册表中检索与Symbol有关的键:
let uid1= Symbol.for('uid');
console.log(Symbol.keyFor(uid1)); //uid
let uid2 = Symbol.for('uid');
console.log(Symbol.keyFor(uid2)); //uid
let uid3 = Symbol('uid');
console.log(Symbol.keyFor(uid3)); //undefined
说明:Symbol全局注册表是一个类似全局作用域的共享环境,也就是说你不能假设目前环境中存在哪些键
四、Symbol与类型强制转换
-
由于其他类型没有与Symbol逻辑等价的值,所以不能将Symbol强制转换为字符串或数字类型。
-
在使用console.log()方法来输出Symbol的内容时,它会调用Symbol的String()方法并输出有用的信息。也可以像下面这样直接调用String()方法来获取相同的内容:
let uid1 = Symbol.for('uid'),
desc = String(uid1);
console.log(desc); //Symbol(uid)
- String()函数调用了uid.toString()方法,返回字符串类型的Symbol描述内容,但如果将Symbol与一个字符串拼接会导致程序抛出错误:
let uidDesc = Symbol.for('uid') + ''; //报错
- Symbol不可以被转为字符串,同样也不能转为数字类型:
let uidSum = Symbol.for('uid') /1; //报错
- 只有在使用逻辑操作符时,Symbol可以正常运行,因为Symbol与JS中的非空值类似,其等价布尔值为true
五、Symbol属性检索
- Object.keys()和Object.getOwnPropertyNames()方法可以检索对象中所有的属性名:前一个方法返回所有的可枚举属性名;后一个方法不考虑属性的可枚举性一律返回。
- Object.getOwnPropertySymbols():ES6中新增一个方法来检索对象中的Symbol属性,其返回值是一个包含所有Symbol自有属性的数组:
let uid1 = Symbol.for('uid');
let uid2 = Symbol.for('uid23');
let object={};
object[uid1]='12345';
object[uid2]='2434';
let symbols = Object.getOwnPropertySymbols(object);
console.log(symbols); //(2) [Symbol(uid), Symbol(uid23)]
console.log(object[uid2]); //2434