【问题标题】:Access the value of Symbol(id) property on an object访问对象上 Symbol(id) 属性的值
【发布时间】:2017-11-27 18:47:20
【问题描述】:

我有一个从 3rd 方 API 获取的对象,如下所示:

{
    name:"Luke Skywalker",
    __typename:"People",
    Symbol(id):"ROOT_QUERY.people."
}

虽然“卢克天行者”可以通过简单的object.name访问, 如何访问此对象的 Symbol(id) 属性的值?

【问题讨论】:

  • 你的意思是objectVariable['Symbol(id)']?对我来说看起来很奇怪。或者objectVariable.Symbol(id)
  • 我试过了,但它不起作用可能Symbol在javascript中有特殊含义
  • 现在这个问题很难回答。您显示的是无效的对象初始化程序,因此我们必须猜测对象的实际创建方式。但是有几种方法可以创建它,具体取决于id 是什么,它们会显着影响问题的答案。 Yury 的回答是一种方式,但请注意,如果该符号是全球注册的,另一种方式将涉及Symbol.for。所以我们只需要更多信息。
  • @T.J.Crowder 这是从 API 获取的响应对象,我想我无法检查对象是如何初始化的,这些值只是从 chrome 控制台复制的。
  • @BakhtiiarMuzakparov:好吧,同样,如何创建符号很重要。无论是 Symbol("id") 还是 Symbol.for("id") 创建它,Chrome 的控制台都会以相同的方式显示符号。详情见我的回答。

标签: javascript ecmascript-6 ecmascript-5


【解决方案1】:

那个对象初始化器是无效的,所以很难回答。

如果这确实是一个符号命名的属性,答案取决于符号是否是全局注册的。

如果不是,您只能通过getOwnPropertySymbols 发现该符号。如果它是唯一的,太好了,你的状态很好:

var data = {
    name:"Luke Skywalker",
    __typename:"People",
    [Symbol("id")]:"ROOT_QUERY.people."
};
console.log(data[Object.getOwnPropertySymbols(data)[0]]);

假设只有一个以符号命名的属性,我们可能不应该这样做。相反,让我们寻找带有描述性字符串"Symbol(id)" 的符号:

var data = {
    name:"Luke Skywalker",
    __typename:"People",
    [Symbol("id")]:"ROOT_QUERY.people."
};
var sym = Object.getOwnPropertySymbols(data).find(function(s) {
  return String(s) === "Symbol(id)";
});
console.log(sym ? data[sym] : "Symbol(id) not found");

但如果它是全局注册的并且你知道它在哪个字符串下注册,你可以使用Symbol.for 来获取它:

var data = {
    name:"Luke Skywalker",
    __typename:"People",
    [Symbol.for("id")]:"ROOT_QUERY.people."
};
console.log(data[Symbol.for("id")]);

【讨论】:

  • 将您标记为答案。第一个选项已经奏效,所以我相信符号当时没有在全球范围内注册。谢谢!
  • @BakhtiiarMuzakparov:如果第二个不起作用,是的,这意味着它没有在字符串"id" 下进行全局注册。请注意,如果他们在 API 升级时向该对象添加其他符号,则需要小心获取正确的符号。我在上面添加了一个(新的)第二个代码块,以帮助您确保获得正确的代码块。
  • 官方文档甚至没有显示这一点有点荒谬:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • @AndroidDev - MDN 不是“官方文档”,它是 Mozilla 的社区驱动的文档站点。 :-) 唯一的官方文档是the spec。 MDN 由世界各地的程序员编写并为他们编写。总的来说,它非常非常好,但这里和那里都有奇怪的差距——任何人都可以解决。 :-) 虽然缺少什么...? This 似乎至少涵盖了上述内容...
【解决方案2】:

您可以使用 Object.getOwnPropertySymbols() 来检索它,但这将检索与对象关联的所有符号。如果您想直接在对象上获取该特定符号,则需要存储该符号对象以供重复使用。

const sym = Symbol(id);
const example = {
  name:"Luke Skywalker",
  __typename:"People",
  [sym]:"ROOT_QUERY.people."
}

console.log(example[sym]) //Equals "ROOT_QUERY.people."

【讨论】:

  • OP 说(在评论中)他们从 API 获取这个对象,所以他们不会有符号(除了从对象中检索它,或者如果它是全局的-注册)。
【解决方案3】:

Symbols 旨在定义唯一的属性名称以避免冲突。因此,您应该可以访问用于构造对象的符号或使用getOwnPropertySymbols 获取所有符号

const obj = {
  [Symbol('id')]: 1
}

console.log(obj[Symbol('id')])

const symbols = Object.getOwnPropertySymbols(obj)

console.log(obj[symbols[0]])

【讨论】:

  • 是的,Symbol.for 的冲突又回来了。
【解决方案4】:

添加到@T.J. Crowder,符号也可以通过Reflect.ownKeys 发现,它会列出所有对象自己的键:属性名称和符号。

const data = {
    name:"Luke Skywalker",
    __typename:"People",
    [Symbol("id")]:"ROOT_QUERY.people."
};

const sym = Reflect.ownKeys(data).find(s => {
  return String(s) === "Symbol(id)";
});
console.log(sym ? data[sym] : "Symbol(id) not found");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 2013-12-02
    • 1970-01-01
    • 2018-05-02
    • 2011-03-09
    • 1970-01-01
    相关资源
    最近更新 更多