新的JavaScript"Symbol"数据类型有哪些可能的使用方案?

Mic*_*zyk 16 javascript types symbols

我只是偶然在JavaScript中,新的(建议ES6,但在Firefox,Chrome和歌剧已经实施)数据类型的文档时Symbol:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol http://people.mozilla.org/~jorendorff/es6-draft.html#sec-symbol-objects

我正在读它,但我想不出可能的使用场景.

文件说:

符号是唯一且不可变的数据类型,可用作对象属性的标识符.

好的,好吧,假设我按照文档说的那样做:

obj[Symbol("a")] = "a";
Run Code Online (Sandbox Code Playgroud)

但是,因为符号('a')总是返回唯一值(对象),并且:

迭代中的符号在...中不可见.

我如何从中检索我的财产obj

var obj = { normalProperty: 'just a string' };
obj[Symbol('a')] = 'a';

document.getElementById('retrieve').addEventListener('click', function() {
  document.write('Stringified object:' + JSON.stringify(obj) + '<br/><br/>');
  document.write('Trying to get Symbol-property value, aaaand...: <br/>');
  document.write(obj[Symbol('a')]); // undefined
}, false);
Run Code Online (Sandbox Code Playgroud)
<button id="retrieve">Retrieve obj's property</button>
Run Code Online (Sandbox Code Playgroud)

编辑

当然,您可以像这样检索它:

var x = Symbol('a');
obj[x] = 'a';
obj[x]; // "a"
Run Code Online (Sandbox Code Playgroud)

但这样做的目的是什么?

提前致谢 :)

man*_*nji 15

在阅读文档并Symbol在chrome中使用此类型稍微玩一下之后,似乎a Symbol是一种定义名称的方式 - 而不是值 - 以及使用符号定义的属性不可见的事实for..in,Object.getOwnPropertyNames()或者使用JSON.stringify()符号对元数据属性有用:

// define metadata symbols
var Metadata = {
        Date: Symbol('Message date')
};

var email = function(recipient, message) {
    this.Recipient = recipient;
    this.Message = message;
    this[Metadata.Date] = new Date();
};

var email1 = new email('@Me', 'test');
JSON.stringify(email1);
// {
//    Recipient: '@Me',
//    Message: 'test'
// }

// Date is still accessible using
email1[Metadata.Date];
// Thu Nov 27 2014 16:50:00 GMT+0000

// Debugging in Console:
// {
//    Recipient: '@Me',
//    Message: 'test'
//    Symbol(Message date): Thu Nov 27 2014 16:50:00 GMT+0000
// }
Run Code Online (Sandbox Code Playgroud)

可以使用该Symbol.for函数使符号全局化,因此元数据名称可以创建一次并在所有项目文件中使用.

使用符号访问值需要在创建时引用符号.Symbol()即使使用相同的描述,每次调用都会创建一个新的调用:

var a = Symbol('a');
var b = Symbol('a');
a != b
// and
a != Symbol('a')
Run Code Online (Sandbox Code Playgroud)

但是,使用创建符号Symbol.for,它将在全局注册表中注册,并且描述成为关键,意味着全局注册表中只存在一个具有相同键的符号:

var a = Symbol.for('a');
var b = Symbol.for('a');
a == b
// and
a == Symbol.for('a')
Run Code Online (Sandbox Code Playgroud)


Gil*_*cas 9

它们几乎可以帮助我们解决命名冲突。每当您想以独特的方式创建属性时,您就应该使用符号。

看看我的例子

const bert = Symbol('Bert');
Run Code Online (Sandbox Code Playgroud)

“伯特”

注意:这不是一个值,而是他们所谓的描述符,因为符号本身只是一个唯一标识符。因此,如果您要想象一个符号是什么,也许您可​​以想象像这样的“sdfasdfa2342134987fgsdfgsdf9808fsfgsd”绝对唯一的符号,这样您就可以确保它永远不会覆盖其中的任何其他代码。

最酷的是如果我创建第二个符号,比如

const person = Symbol('Bert')
Run Code Online (Sandbox Code Playgroud)

你可以看到我又用了“Bert”。因为我将它们描述为同一件事,所以它们会是相同的吗?

const bert = Symbol('Bert');
Run Code Online (Sandbox Code Playgroud)
在此输入图像描述

如果您要创建类的对象,这可能很有用。

const person = Symbol('Bert')
Run Code Online (Sandbox Code Playgroud)

但后来又有一个叫吉尔伯特,所以就出现了命名冲突。想象一下,如果您正在处理数以百万计的数据。因此,我们可以使用符号来命名他们,而不是使用人名或某种唯一标识符。

const bert = Symbol('Bert');
const person = Symbol('Bert');


console.log(bert);
console.log(person);
console.log(bert === person);
console.log(bert == person);
Run Code Online (Sandbox Code Playgroud)

关于符号的另一件事是它们不可枚举,这意味着如果我要这样做,我们就无法循环它们

  for (const person in classRoom) {
    console.log(person);
  }
Run Code Online (Sandbox Code Playgroud)

我什么也没得到。

如果您确实想访问所有符号,因为它们是您想要获取的一些信息,您可以使用对象方法。

  const syms = Object.getOwnPropertySymbols(classRoom);
  const data = syms.map(sym => classRoom[sym]);
  console.log(data);
Run Code Online (Sandbox Code Playgroud)