ES6 引入了新的基本类型:Symbol。
创建 Symbol
var symbol = Symbol("first");
console.log(typeof symbol); //"symbol"
var a = new Symbol("first"); //抛出错误:Symbol is not a constructor
Symbol 函数接受一个可选的参数,通常都是附件一段文本来描述当前 Symbol 的用途;使用 new 方式来调用 Symbol 函数抛出错误,说明 Symbol 函数没有 [constructor] 属性。
Symbol 的使用
通常 Symbol 类型的变量用于声明对象的属性名,这样 Object.keys() 或 Object.getOwnPropertyNames() 的方法就没办法获取到 Symbol 声明的属性。起到一定的保护作用,防止它们被意外的修改。
var symbolKey = Symbol("a");
// 第一种方式:使用可计算属性添加
var object = {
[symbolKey]: 100
}
// 第二种方式
Object.defineProperty(object, symbolKey, { value: 100 });
// 第三种方式
Object.defineProperties(object, {
[symbolKey]: {
value: 100
}
});
console.log(Object.keys(object)); // Array []
console.log(Object.getOwnPropertySymbols(object)); // Array [ Symbol(first) ];
ES6 中新增加一个 Object.getOwnPropertySymbols() 方法来检索对象中的 Symbol 属性。
Symbol 共享
在不同代码中共享同一个 Symbol 标识符,ES6 中提供一个可以随时访问的全局 Symbol 注册表。
// 示例1:
var a = Symbol("111");
var b = Symbol("111");
console.log(a == b, a === b); // false, false
// 示例2:
var key = Symbol.for("aa");
var key1 = Symbol.for("aa");
console.log(key === key1); // true
var object = {
[key]: 100,
[key1]: 200
}
console.log(object[key],object[key1]); // 200, 200
首先使用 Symbol() 创建两个相同文本描述的 Symbol 变量,但这两个完全不是同一个东西。
使用 Symbol.for() 创建的就完全相同,Symbol.for() 首先在全局 Symbol 注册表中搜索键为 "aa" 的 Symbol 是否存在,如果存在则返回已有的 Symbol ,否则在全局注册表中新建一个 Symbol ,在返回改 Symbol。
在示例2中看到由于 key 和 key1 都是同一个 Symbol ,所以对象中 [key1] 覆盖了 [key] 的值。相当于同一个东西有两个名称,本质还是一个东西。
well-known Symbol
Symbol.isConcatSpreadable
该属性时一个布尔值,这个属性要手动添加到对象中,用于增强对象类型 concat() 方法。如果属性值为 true ,则表示对象有 length 属性和数字键,将对象下的数值型属性值独立添加到 concat() 中。
var object = {
0: "a",
2: "b",
length: 3,
[Symbol.isConcatSpreadable]: true
};
var array = ["value"].concat(object);
console.log(array); // Array [ "value", "a", undefined, "b" ];
上面代码定义一个类数组对象 object,有一个 length 属性和一些数字键属性,由于 Symbol.isConcatSpreadable 为 true ,根据 length 值来把数字键属性添加到 concat() 中。object 中没有数字键 1 ,所以添加一个 undefined。
Symbol.hasInstance
instanceof 运算符相信大家都不会陌生,用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链。
每个函数都有一个 Symbol.hasInstance 方法,该方法接受一个参数,即要检查的值。自定义这个 Symbol.hasInstance 方法,就可以随意改变 instanceof 的运作方式。
function Fun () {
// 代码
}
Object.defineProperty(Fun, Symbol.hasInstance, {
value: function (val) {
return false;
}
})
var object = new Fun();
console.log(object instanceof Fun); // false
示例中 object 是通过 Fun 函数的实例,由于我改写了 Fun 中的 Symbol.hasInstance 方法,返回 false,所以 instanceof 运算符得到的结果为 false 。
这个示例其实很难明白 Symbol.hasInstance 的运作机制,我查阅资料大概理解了。
object instanceof Fun;
//相当于
Fun[Symbol.hasInstance](object);
well-known Symbol 还有很多就不逐个列举了,有兴趣到 MDN Symbol 来看看