JavaScript - 计算属性 - 深度混淆

JavaScript - Computed properties - deep confusion

似乎我对 JavaScript 中的计算属性感到很困惑。

当我定义一个对象并将 [d] 作为键(作为 属性 key/name)时,这个 [d] 实际上做了什么?似乎对于某些值 d 它计算 s = d.toString() 并使用该值 s 作为 属性 键。 但是对于其他值 d (例如,当 d 是一个符号时)它实际上使用符号的值作为键。

所以 [d] 的这种双重行为(作为语法结构)似乎令人困惑。有人可以深入解释这是如何工作的吗?

还有其他特殊情况吗?还是当 d 是 Symbol 时我们有这种特殊行为?

回到基础:什么事物可以是对象的keys/names属性?它只是字符串还是只是字符串和符号,还是还有一些额外的......?

示例:

var symbol = Symbol("test");

function Animal(name){
 this.name = name;
}

Animal.prototype = {};
Animal.prototype.constructor = Animal;

function Dog(breed){
    this.breed = breed;
    this.name = "Dog";
    this.s = symbol;
}

Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

console.log("001");
var d = new Dog("Sharo");
for (let x in d){
    console.log(x, ":", d[x]);
}

console.log("002");
d = new Object();
for (let x in d){
    console.log(x, ":", d[x]);
}

console.log("003");
d = new Number(5);
for (let x in d){
    console.log(x, ":", d[x]);
}

var d1 = {};
var d2 = {};

var d = new Dog("Sharo");

var m = {[d1] : 5, [d2] : 10, [d] : 20, z : 100, symbol: 2000, [symbol] : 5000};

console.log("============================");
console.log(m);

for (let x in m){
    console.log(x, ":", m[x]);
}
console.log("============================");

由于似乎没有人有兴趣回答这个问题,我将根据上面得到的评论自己回答,因此我不再感到困惑。

请注意,这里的答案是基于 ES6 的。我的意思是...谁知道 JavaScript 的未来还会怎样 :)

When I define an object and I put [d] as a key (as a property key/name) what does this [d] actually do? Seems that for some objects d it calculates s = d.toString() and uses that value s as the property key. But for other objects d (e.g. when d is a Symbol) it uses really the Symbol's value as the key.

是的,没错。当 d 是 Symbol 时,直接使用它的值。当 d 不是 Symbol 时,它的值被强制转换为一个字符串,并且该字符串用作 属性 name/key。强制转换更像是 String(d) 而不是 d.toString()

So this dual behavior of [d] (as a syntax construct) seems confusing. Could someone explain in depth how this works?

上面已经解释过了。

Are there other special cases btw? Or is it just when d is a Symbol when we have that special behavior?

没有其他"special cases"。从 ES6 开始,只有字符串和符号可以是 属性 键。

Back to the basics: what things can be keys/names of properties of an object? Is it just strings or just strings and symbols or is there also something additional... ?

如前所述,从 ES6 开始,只有字符串和符号可以是 属性 键。

参考文献:

(1) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors

"Property names are string or Symbol. Any other value, including a number, is coerced to a string."

(2) https://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey

在对另一个答案的评论中,您说您认为 属性 键总是字符串。在 ES2015 之前,它们 。 :-)

So this dual behavior of [d] (as a syntax construct) seems confusing. Could someone explain in depth how this works?

从 ES2015 开始,Symbols 被添加到语言中,对象 属性 键可以是字符串或 Symbols。所以当你这样做时:

const obj = {
    [d]: "foo"
};

...计算出的 属性 键 ([d]: "foo") 的一部分是这样工作的:

  1. value 为计算表达式 "foo"
  2. 的结果
  3. keyValue 为计算表达式 d
  4. 的结果
  5. 如果keyValue是一个Symbol,让key = keyValue;否则,设 key = String(keyValue)
  6. obj 上的 属性 key 设置为值 value

为了清楚起见,我在其中省略了一些细节。您可以在规范中的 ToPropertyKey 抽象操作中看到,只要将值用作 属性 键(在上面的对象文字中,或者访问对象 属性 通过括号符号等)。

Are there other special cases btw? Or is it just when d is a Symbol when we have that special behavior?

Back to the basics: what things can be keys/names of properties of an object? Is it just strings or just strings and symbols or is there also something additional... ?

只是符号和字符串。 :-) 与其说 Symbol 是一个 特例 ,还不如说 属性 键以前总是字符串,现在它们可以是字符串 符号。

(有趣的事实:在规范中,they define "property key" as the string or Symbol that identifies a property, and "property name" as a property key that's a string. But don't rely on it, the spec itself is a bit inconsistent, and the Object.keys method — which returns an array of property names, not property keys — existed before that terminology was added in ES2015. And then they added a keys method to arrays that returns an iterator of numbers [the indexes 在数组中。有趣有趣...:-))

在 ES2015 中指定所有返回或循环遍历 属性 名称的 ES5 和更早版本的操作,以忽略符号键控属性。所以for-inObject.keysObject.getOwnPropertyNames都只看字符串键控的属性。 ES2015 添加了 Reflect.ownKeys(包括字符串和符号)和 Object.getOwnPropertySymbols(仅包括自己的符号键属性)。


旁注:

Seems that for some objects d it calculates s = d.toString() and uses that value s as the property key...

不只是对象,它更像是 String(d)(尽管如果 d 是一个对象,则结果相同)。任何不是字符串或符号的内容都将转换为字符串。

...But for other objects d (e.g. when d is a Symbol) it uses really the Symbol's value as the key.

Symbols 不是对象,Symbol 是原始类型。但是,是的,如果 属性 键是一个 Symbol,则直接使用它,而不是转换为字符串。