剑客
关注科技互联网

第七元素

typeof Symbol(): symbol

Javascript 一共有6种数据类型:Undefined、Null、Number、String、Object、Boolean。今天,我们先看看第七种:Symbol。

为什么要产生新的类型

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

可见,这个类型是提供了一个不可更新的特性,这样可以保证别人不会覆盖你的属性。下面我们来看看它的样子:

语法:Symbol([description])

let mySymbol = Symbol();
let mySymbol2 = Symbol('this is just a desction');

没有new,里面的参数只是一个描述,这就是对这个构造器的最简单解释了。

实际用途

当你第一眼看到Symbol,你会在想,什么鬼,不想用。当你知道它的特性,会让你不得不重视它。我们知道,对象的键可以用数字或字符串,但这样的话就不能保证唯一性,当我们知道symbol的特性,就可以拿它来做试验了。

  1. 可以作为键名:

let mySymbol = Symbol();
let obj = {};
obj[mySymbol] = 'hello';

如此简单的一句, obj
对象就使用了 mySymbol
这个symbol作为键属性,它是一个symbol,不是一个字符串。你不能用点去访问它了,类似的,for-in去枚举一个含有symbol键的对象,也不会打印出来(看例子)。既然它的作用就是保证唯一,我们就可以在这种需求下满足了。

  1. 唯一性

let a = 'hello';
let b = 'hello';

console.log( a === b); // true

let a = Symbol('hello');
let b = Symbol('hello');

console.log( a === b); // false

已有的数据类型,我们很熟悉。再来看看symbol,即使是一样的描述,它们也是不相同的。

举一个例子:

  1. 例1

const obj = {
  [Symbol('age')] : 20,
  [Symbol('name')] : 'liya',
  ok: true
}

for( var i in obj) {
  console.log(obj[i]);
}

运行之后,你只会得到一个true。for-in 并不能访问到symbol,想要访问,你必须用到专用的api。

  1. 例2

log.levels = {
    DEBUG: Symbol('debug'),
    INFO: Symbol('info'),
    WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');

咋看也没有什么Symbol的事,事实上在ES5时代,你必须这样写:

log.levels = {
    DEBUG: 1,
    INFO: 2,
    WARN: 3,
};

这样写的坏处是,值不是唯一的,某天如果被人把DEBUG的值改成了3,那你不是顿时懵了。用Symbol的好处在于,你不用理会它的值是什么,它只是一个占位符,并且唯一。

注册表

每个symbol是唯一的,即使两个描述一样的symbol也不相等。symbol的弱封装机制:模块创建了几个symbol,可以在任意对象上使用,无须担心与其它代码创建的属性产生冲突。它只在当前的作用域生效,如果要在全局中共享,就要在全局中注册,使用 Symbol.for()
去注册。

Symbol('ok');
Symbol.for('ok');

console.log(Symbol('ok') === Symbol('ok'));           // false
console.log(Symbol.for('ok') === Symbol.for('ok'));   // true

第一句和第二句都是创建一个Symbol,不同的是,Symbol.for不再是每次创建不同的symbol,它会从注册表中找,找到了就会返回。无论你访问几次,都不会创建新的symbol。全局的symbol可以跨域和在多个页面中使用。

最后

查了一些资料,但也不是太过清楚,毕竟用的人还不多。期待在ES6后面能够让更多人去使用,类似Symbol这种api,大家只是瞄一眼就不再关注了,除了文档不够,更多的是设计上的问题。ES6出了有一段时间,有多少api能够深入人心,我想只有在坐的各位比较清楚。

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址