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

时间:2014-11-27 14:17:25

标签: javascript types symbols

我只是偶然发现了新的文档(针对ES6提出,但已经在Firefox,Chrome和Opera中实现)的数据类型在JavaScript中,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";

但是,因为Symbol('a')总是返回唯一值(object)和:

  

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

如何从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);
<button id="retrieve">Retrieve obj's property</button>

修改

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

var x = Symbol('a');
obj[x] = 'a';
obj[x]; // "a"

但这样做的目的是什么?

提前致谢:)

2 个答案:

答案 0 :(得分:13)

阅读文档并使用Chrome中的Symbol类型稍微玩一下后,似乎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
// }

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

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

var a = Symbol('a');
var b = Symbol('a');
a != b
// and
a != Symbol('a')

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

var a = Symbol.for('a');
var b = Symbol.for('a');
a == b
// and
a == Symbol.for('a')

答案 1 :(得分:0)

它们几乎可以帮助我们进行命名冲突。每当您想以独特的方式创建属性时,都应该获取符号。

看看我的例子

const bert = Symbol('Bert');

“ Bert”

  

注意:这不是一个值,这就是他们所说的描述符,   因为符号本身只是唯一的标识符。所以如果你是   可视化一个符号,也许您可​​以可视化为   像这样的东西“ sdfasdfa2342134987fgsdfgsdf9808fsfgsd”绝对   唯一的符号,以便您可以确保它永远不会覆盖   那里的任何其他代码。

这很酷,如果我创建另一个符号,例如

const person = Symbol('Bert')

您可以看到我再次使用了“ Bert”。因为我将它们描述为同一件事,所以它们会一样吗?

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


console.log(bert);
console.log(person);
console.log(bert === person);
console.log(bert == person);
enter image description here

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

  const classRoom = {
    'Mia' : { grade: 50, gender: 'female' },
    'Gilbert': { grade: 80, gender: 'male' },
    'Gilbert' { grade: 80, gender: 'male' },
  };

但是随后您有另一个名为Gilbert的人,因此在那里发生了命名冲突。因此,想象一下您是否正在处理数百万个数据。因此,我们可以使用符号来命名他们,而不是使用人名或使用某种唯一标识符。

  const classRoom = {
    [Symbol('Mia')] : { grade: 50, gender: 'female' },
    [Symbol('Gilbert')]: { grade: 80, gender: 'male' },
    [Symbol('Gilbert')]: { grade: 80, gender: 'male' },
  };

关于符号的另一件事是它们不可枚举,这意味着如果我愿意的话,我们无法遍历它们

  for (const person in classRoom) {
    console.log(person);
  }

我什么也没得到。

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

  const syms = Object.getOwnPropertySymbols(classRoom);
  const data = syms.map(sym => classRoom[sym]);
  console.log(data);