将符号引入ES6的动机是什么?

更新:最近Mozilla发表了一篇精彩的文章。如果您好奇,请阅读它。

您可能知道,他们计划在 ECMAScript 6 中包含新的 Symbol 基元类型(更不用说其他一些疯狂的东西了)。我一直认为Ruby中的概念是不必要的。我们可以很容易地使用纯字符串,就像我们在JavaScript中所做的那样。现在他们决定用这个使JS中的事情复杂化。:symbol

我不明白动机。有人可以向我解释一下我们是否真的需要JavaScript中的符号吗?


答案 1

在Javascript中引入符号的最初动机是启用私有属性。

不幸的是,他们最终被严重降级。它们不再是私有的,因为您可以通过反射(例如,使用或代理)找到它们。Object.getOwnPropertySymbols

它们现在被称为唯一符号,它们的唯一预期用途是避免属性之间的名称冲突。例如,ECMAScript 本身现在可以通过某些方法引入扩展钩子,您可以将这些方法放在对象上(例如,定义它们的迭代协议),而不会冒着与用户名冲突的风险。

这是否足够强大,可以成为在语言中添加符号的动机,这是值得商榷的。


答案 2

符号不能保证真正的隐私,但可用于分离对象的公共和内部属性。让我们举个例子,我们可以用它来拥有私有属性。Symbol

让我们举个例子,其中对象的属性不是私有的。

var Pet = (function() {
  function Pet(type) {
    this.type = type;
  }
  Pet.prototype.getType = function() {
    return this.type;
  }
  return Pet;
}());

var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Modified outside
console.log(a.getType());//Output: null

在上面,类属性不是私有的。为了使其私有,我们必须创建一个闭包。下面的示例说明了如何使用闭包使私有。Pettypetype

var Pet = (function() {
  function Pet(type) {
    this.getType = function(){
      return type;
    };
  }
  return Pet;
}());

var b = new Pet('dog');
console.log(b.getType());//dog
b.type = null;
//Stays private
console.log(b.getType());//dog

上述方法的缺点:我们为创建的每个实例引入了额外的闭包,这可能会损害性能。Pet

现在我们介绍.这可以帮助我们使属性私有,而无需使用额外的不必要的闭包。代码示例如下:Symbol

var Pet = (function() {
  var typeSymbol = Symbol('type');
  function Pet(type) {
    this[typeSymbol] = type;
  }
  Pet.prototype.getType = function(){
    return this[typeSymbol];
  }
  return Pet;
}());

var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Stays private
console.log(a.getType());//Output: dog