1
主要知识点:创建符号值、使用符号值、共享符号值、符号值转换。检索符号值属性以及知名符号

图片描述

《深入理解ES6》笔记 目录

ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

创建符号值

let firstName = Symbol();
let person = {};
person[firstName] = "Nicholas";
console.log(person[firstName]); // "Nicholas"
console.log(firstName ); // Symbol()
typeof firstName //"symbol"
由于符号值是基本类型的值,因此调用 new Symbol() 将会抛出错误。你可以通过 new
Object(yourSymbol) 来创建一个符号实例,但尚不清楚这能有什么作用。
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)"

使用符号值

可以在任意能使用“需计算属性名”的场合使用符号,还可以在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"

共享符号值

如果需要在应用中需要在两个不同的对象类型中使用同一个符号属性,用来表示一个唯一标识符,可以使用Symbol.for()创建共享符号值;
Symbol.for()方法仅接受单个字符串类型的参数,作为目标符号值的标识符,同时此参数也会成为该符号的描述信息。

let uid = Symbol.for("uid");
let object = {};
object[uid] = "12345";
console.log(object[uid]); // "12345"
console.log(uid); // "Symbol(uid)"

先搜索全局符号注册表,如果已有,则返回这个已存在的符号值;否则,会创建一个新的符号值,并使用该键值将其记录到全局符号注册表中,然后返回这个新的符号值。

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"
//uid3在全局注册表中并不存在,会返回undefined
let uid3 = Symbol("uid");
console.log(Symbol.keyFor(uid3)); // undefined

符号值的转换

类型转换是 JS 语言重要的一部分,能够非常灵活地将一种数据类型转换为另一种。然而符号类型在进行转换时非常不灵活,因为其他类型缺乏与符号值的合理等价,尤其是符号值无法被转换为字符串值或数值,在逻辑运算符中会被认为等价于 true。

let uid = Symbol.for("uid"),
desc = uid + ""; // 引发错误!
// 使用console.log()  来展示符号值的输出,能这么做是由于自动调用了符号的  String()  方法来产生输出。你也可以直接调用  String()  方法来获取相同结果
let uid = Symbol.for("uid"),
desc = String(uid);
console.log(desc); // "Symbol(uid)"

检索符号属性

Object.keys() 与 Object.getOwnPropertyNames() 方法可以检索对象的所有属性名称,但不能返回符号类型的属性,ES6 新增Object.getOwnPropertySymbols() 方法,以便让你可以检索对象的符号类型属性。
Object.getOwnPropertySymbols() 方法会返回一个数组,包含了对象自有属性名中的符号值:

let uid = Symbol.for("uid");
let object = {
    [uid]: "12345"
};
let symbols = Object.getOwnPropertySymbols(object);
console.log(symbols.length); // 1
console.log(symbols[0]); // "Symbol(uid)"
console.log(object[symbols[0]]); // "12345"

sevencui
355 声望32 粉丝