在 JS 已有的基本类型(字符串、数值、布尔类型、 null 与 undefined )
ES6 引入 了一种新的基本类型:符号( Symbol )
1.创建符号值
2.使用符号值
3.共享符号值
创建符号值
符号没有字面量形式,这在 JS 的基本类型中是独一无二的,有别于布尔类型的 true 或数 值类型的42 等等。
你可以使用全局 Symbol 函数来创建一个符号值,
let firstName = Symbol();
let person = {};
person[firstName] = "Nicholas";
console.log(person[firstName]); // "Nicholas"
由于符号值是基本类型的值,因此调用 new Symbol() 将会抛出错误。
let firstName = Symbol("first name");
let person = {};
person[firstName] = "Nicholas";
console.log("first name" in person); // false
console.log(person[firstName]); // Nicholas
console.log(firstName); // Symbol(first name)
Symbol 函数还可以接受一个额外的参数用于描述符号值,该描述并不能用来访问对应属性,
但它能用于调试
let symbol = Symbol("test symbol");
console.log(typeof symbol); // symbol
由于符号是基本类型的值,因此你可以使用 typeof 运算符来判断一个变量是否为符号。
使用符号值
可以在任意能使用“需计算属性名”的场合使用符号
Object.defineProperty() 或 Object.defineProperties()
let firstName = Symbol("first name");
// 使用一个需计算字面量属性
let person = {
[firstName]: "Nicholas"
};
// 让该属性变为只读
Object.defineProperty(person, firstName, { writable: false });
let lastName = Symbol("last name");
Object.defineProperties(person, {
[lastName]: {
value: "Zakas",
writable: false
}
});
console.log(person[firstName]); // "Nicholas"
console.log(person[lastName]); // "Zakas"
这个例子首先使用对象的“需计算字面量属性”方式创建了一个符号类型的属性 firstName , 该属性使用 getOwnPropertyDescriptor 查看时显示为可枚举( enumerable: true ),但无 法用 for-in 循环遍历,也不会显示在 Object.keys() 的结果中。下一行代码将该属性设置为 只读。接下来,使用 Object.defineProperties() 方法创建了一个只读的符号类型属性lastName ,而此时再次使用了“需计算字面量属性”方式,并将其作为第二个调用参数的一部 分。
共享符号值
例如:假设在应用中需要在两个不同的对象 类型中使用同一个符号属性,用来表示一个唯一标识符。跨越文件或代码来追踪符号值是很 困难并且易错的,为此, ES6 提供了“全局符号注册表”供你在任意时间点进行访问
创建共享符号值,应使用 Symbol.for() 方法而不是Symbol()方法。 Symbol.for() 方法仅接受单个字符串类型的参数,作为目标符号值的标识符,同时此参数也会成为该符号 的描述信息。
let uid = Symbol.for("uid");
let object = {};
object[uid] = "12345";
console.log(object[uid]); // 12345
console.log(uid); // Symbol(uid)
Symbol.for() 方法首先会搜索全局符号注册表,看是否存在一个键值为 "uid" 的符号值。 若是,该方法会返回这个已存在的符号值;
否则,会创建一个新的符号值,并使用该键值将 其记录到全局符号注册表中,然后返回这个新的符号值。
这就意味着此后使用同一个键值去 调用Symbol.for() 方法都将会返回同一个符号值,
如下:
let uid = Symbol.for("uid");
let object = {
[uid]: "12345"
};
console.log(object[uid]); // "12345"
console.log(uid); // "Symbol(uid)"
let uid2 = Symbol.for("uid");
console.log(uid === uid2); // true
console.log(object[uid2]); // "12345"
console.log(uid2); // "Symbol(uid)"
另一个独特用法,你可以使用 Symbol.keyFor() 方法在全局符号注册表中根据符号值检索出对应的键值:
let uid = Symbol.for("uid");
console.log(Symbol.keyFor(uid)); // "uid"
let uid2 = Symbol.for("uid");
console.log(Symbol.keyFor(uid2)); // "uid"
let uid3 = Symbol("uid");
console.log(Symbol.keyFor(uid3)); // undefined
符号值 uid3 在全局符号注册表中并不存在,因此没有关联的键值, Symbol.keyFor() 方法只会返回 undefined
网友评论