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

Javascript 将符号引入ES6的动机是什么?,javascript,symbols,ecmascript-harmony,ecmascript-6,Javascript,Symbols,Ecmascript Harmony,Ecmascript 6,更新:最近出现了一个问题。如果你好奇的话,读一读 您可能知道,它们是ECMAScript 6中的新符号基元类型(更不用说其他一些疯狂的东西了)。我一直认为Ruby中的:symbol概念是不必要的;我们可以很容易地使用普通字符串,就像在JavaScript中一样。现在他们决定用这个来让JS中的事情复杂化 我不明白动机。有人能解释一下我们是否真的需要JavaScript中的符号吗?将符号引入JavaScript的最初动机是启用私有属性 不幸的是,它们最终被严重降级。它们不再是私有的,因为您可以通过反

更新:最近出现了一个问题。如果你好奇的话,读一读

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


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

将符号引入JavaScript的最初动机是启用私有属性

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

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


这是否足以成为在语言中添加符号的动机还有争议。

符号不能保证真正的隐私,但可以用来区分对象的公共属性和内部属性。让我们举一个例子,我们可以使用
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
上面的
Pet
class属性
type
不是私有的。为了使其私有化,我们必须创建一个闭包。下面的示例说明了如何使用闭包将
type
设为私有

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

以下是我的看法。符号通过防止对象的键/属性通过一些常用方法(如object.keys()和JSON.stringify()公开)而提供“额外的隐私级别”


尽管给定了一个对象本身,这些属性仍然可以通过反射、代理、object.getOwnPropertySymbols()等公开,但没有自然的方法可以通过一些直接的方法访问它们,从OOP的角度来看,这些方法有时可能就足够了。

符号是一种新的,可以用作对象中唯一属性名称的特殊类型的对象。使用符号而不是字符串允许不同的模块创建彼此不冲突的属性。符号也可以被有效地私有化,因此任何尚未直接访问符号的人都无法访问其属性

符号是一个新的基元,就像数字、字符串和布尔基元一样。与其他原语不同,符号没有文字语法(例如,
string
如何拥有
'
)-创建它们的唯一方法是使用
Symbol
构造函数,方法如下:

let symbol = Symbol();
实际上,符号只是将属性附加到对象上的一种稍有不同的方式-您可以轻松地将众所周知的符号作为标准方法提供,就像
object.prototype.hasOwnProperty
,它出现在从
对象继承的所有内容中

下面是
符号
基本类型的一些优点

符号具有内置的可调试性 可以为符号提供一个描述,它实际上只是用于调试,以便在将它们记录到控制台时让生活更轻松

符号可以用作对象键 这就是符号变得非常有趣的地方。它们与物体紧密地交织在一起。符号可以指定为对象的键,这意味着您可以为对象指定无限数量的唯一符号,并保证这些符号不会与字符串键或其他唯一符号冲突

符号可以用作唯一值 假设您有一个日志库,其中包括多个日志级别,例如
logger.levels.DEBUG
logger.levels.INFO
logger.levels.WARN
等等。在ES5代码中,您希望生成这些字符串(因此
logger.levels.DEBUG=='DEBUG'
)或数字(
logger.levels.DEBUG==10
)。这两个都不理想,因为这些值不是唯一的值,但符号是唯一的!所以
logger.levels
就变成了:

log.levels={
调试:符号('DEBUG'),
信息:符号('INFO'),
警告:符号(‘警告’),
};
日志(log.levels.DEBUG,“调试消息”);
日志(log.levels.INFO,“信息消息”);

阅读更多信息。

这篇文章是关于
Symbol()
,提供了我能找到/制作的实际例子以及我能找到的事实和定义

##TLDR

Symbol()
是ECMAScript 6(ES6)发布时引入的数据类型

关于这个符号有两个奇怪的事实

  • 第一个数据类型,也是JavaScript中唯一一个没有文本的数据类型

  • 任何用
    Symbol()
    定义的变量都会获得唯一的内容,但实际上并非如此

  • 任何数据都有自己的符号,对于相同的数据,符号是相同的。更多信息请参见以下段落,否则它不是TLRD;:)

##如何初始化符号

###一,。获取具有可调试值的唯一标识符的步骤 您可以这样做:

var mySymbol1 = Symbol();
var mySymbol2 = Symbol("some text here");
或者这样:

var mySymbol1 = Symbol();
var mySymbol2 = Symbol("some text here");
无法从符号中提取
“此处的某些文本”
字符串,它只是用于调试目的的描述。它不会以任何方式改变符号的行为。尽管如此,您可以
console.log
it(这是公平的,因为
var a1 = Symbol.for("test");
var a2 = Symbol.for("test");
console.log(a1 == a2); //true!
var persons = {"peter":"pan","jon":"doe"};
console.log(persons.peter);
// pan
var persons = {"peter":"first", "peter":"pan"};
 var a = Symbol("peter");
 var b = Symbol("peter");
 console.log(a == b);
 // false
 var firstPerson = Symbol("peter");
 var secondPerson = Symbol("peter");
 var persons = {[firstPerson]:"first", [secondPerson]:"pan"};
 console.log(persons[a]);
 // first
 console.log(persons[b]);
 // pan
var anObject = {};
var fruit = "apple";    

Object.defineProperty( anObject, fruit, {
    enumerable: false,
    value: "green"
});
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //green
console.log(anObject.apple); //green
fruit = Symbol("apple");
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //undefined
console.log(anObject.apple); //undefined
 function isSymbol ( variable ) {
     return typeof someSymbol === "symbol";
 }

 var a_Symbol = Symbol("hey!");
 var totally_Not_A_Symbol = "hey";

 console.log(isSymbol(a_Symbol)); //true
 console.log(isSymbol(totally_Not_A_Symbol)); //false