Table of Content

新的基本类型:符号 (Symbol),刚刚设计出来的时候的被用于创建对象的私有成员.也是javascript开发者一直期待的一个功能特性.这个私有名称最后就成了ES6 中的符号.

6.1 创建symbol

Symbol没有字面量的形式.可以用全局的symbol函数来创建一个符号值:

let first = Symbol('frist');
let obj = {};

obj[first] = '大明王朝1566';
console.log(obj[first])

以上代码创建了一个symbol类型 frist 变量.并把它作为obj对象的一个属性.每次访问属性都要使用这个symbol符号值.

因为symbol基本类型值.因为不能使 new 操作符,如果使用会报错.但是可以通过 new Object(Symbol()) 来创建一个符号实例,在经验中和 Symbol() 没有任何的区别.

Symbol还可以接受一个参数用于描述符号值.可用开发调试.比如:

let first = Symbol('frist');
let obj = {};

obj[first] = '大明王朝1566';
console.log(obj[first])

console.log(first)  //Symbol(frist)

符号的描述信息存在内部属性[[desription]]中.当Symbol的toString()方法被调用(隐式或显示).这个信息就会被读取.

因为是基本类型,所以可以使用typeof 操作符来判断一个变量是否为Symbol类型

let first = Symbol('frist');
console.log(typeof first)  //symbol

6.2 使用Symbol

以上的例子已经展示了符号的方括号的用法,还能在对象的"需计算字面量属性名"中去使用Symbol.也可以在Object.defineProperty() 或 Object.defineProperties() 调用中使用它,比如:

let first = Symbol('frist');
// 使用一个需计算的字面量属性
let obj = {
    [first]:"朱高炽"
}
// 让这个属性变为只读
Object.defineProperty(obj,first,{
    writable:false
});

let last = Symbol('last');
Object.defineProperties(obj,{
    [last]:{
        value:"朱厚照",
        writable:false
    }
})

console.log(obj[first])
console.log(obj[last])

以上使用了字面量属性方式创建了一个符号类型的属性first,可以使用Object.getOwnPropertyDescriptor()查看属性enumerable:true.显示是可以允许遍历,但无法用for-in遍历,也不会显示在Object.keys()结果中。

6.3 共享

在不同的代码中使用相同的符号值,比如,在一个应用中需要在两个不同的对象类型中使用同一个符号属性。用来表示一个唯一的标识符。为此ES6提供了一个“全局符号注册表”,允许我们在任意时间点上去访问。

如果想要创建一个共享符号,需要使用symbol.for()方法,比如:

let userid = Symbol.for("userid")
let obj = {};
obj[userid] = '4324234243';
console.log(obj[userid]);
console.log(userid); //Symbol(userid)

Symbol.for()方法首先第一步会搜索全局的符号注册表。查询是否存在一个名为“userid”的Symbol的值。如果存在,这个方法会返回已经存在的值,否则就会创建一个新的值。并且使用这个值把它记录到全局符号注册表中。再返回新值。

这就是说之后使用同一个值去调用 Symbol.for()方法。都会返回同一个符号值。比如:

let u = Symbol.for('u');
let obj = {
    [u]:'1566'
}

console.log(obj[u]);
console.log(u)

let u2 = Symbol.for('u');

console.log(u2 === u)  //true
console.log(obj[u2]);
console.log(u2) //Symbol(u)

在以上这个案例中。u和u2包含同一个symbol值。因此可以互换使用,第一次调用Symbol.for()方法。创建了这个符号值,而第二次调用全局符号注册表中把它搜索出来。

另外还有一个方法Symbol.keyFor()方法可以在全局符号注册表中根据符号值找出对应的键值。比如:

let name = Symbol.for('name');
console.log(Symbol.keyFor(name))  //name

let name2 = Symbol.for('name');
console.log(Symbol.keyFor(name2))  //name

let name3 = Symbol('name');
console.log(Symbol.keyFor(name3))  //undefined

在以上这个案例中.name 和 name2 都返回了键值 "name".但是name3.在全局符号注册表中不存在.所以并没有关联的健值.所以只能是undefined.

全局符号注册表,可以简单的理解为全局作用域.一个共享的环境.

Leave a Reply

Your email address will not be published.