JavaScript - Computed properties - deep confusion

£可爱£侵袭症+ 提交于 2019-12-23 12:02:22

问题


Seems I am quite confused by computed properties in 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 values d it calculates s = d.toString() and uses that value s as the property key. But for other values d (e.g. when d is a symbol) it uses really the symbol's value as the key.

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?

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... ?

Example:

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("============================");

回答1:


Since no one seems interested in answering this question I will answer it myself based on the comments which I got above, and due to which I am not confused anymore.

Note that this answer here is ES6 based. I mean... who knows what else the JavaScript future will hold :)

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.

Yes, that's correct. When d is a Symbol its value is used directly. When d is anything but Symbol its value is coerced to a string and that string is used as the property name/key. The coercion is more like String(d) rather than d.toString().

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

Already explained above.

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

There are no other "special cases". As of ES6 only strings and symbols can be property keys.

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... ?

As already said, as of ES6 only strings and symbols can be property keys.

References:

(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




回答2:


In a comment on another answer you said you thought property keys were always strings. They were, until ES2015. :-)

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

As of ES2015, Symbols were added to the language, and object property keys became able to be either strings or Symbols. So when you do:

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

...the computed property key ([d]: "foo") part of that works like this:

  1. Let value be the result of evaluating the expression "foo"
  2. Let keyValue be the result of evaluating the expression d
  3. If keyValue is a Symbol, let key = keyValue; otherwise, let key = String(keyValue)
  4. Set the property key on obj to the value value

I've left out a couple of details in there for clarity. You can see that in the ToPropertyKey abstract operation in the specification, which is used whenever a value is used as a property key (in an object literal as above, or when accessing an object property via brackets notation, etc.).

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... ?

Just Symbol and string. :-) It's not so much that Symbol is a special case, it's just that where it used to be that property keys were always strings, now they can be strings or Symbols.

(Fun fact: In the spec, 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 in the array]. Fun fun fun... :-) )

All ES5 and earlier operations that returned or looped over property names were specified in ES2015 to ignore Symbol-keyed properties. So for-in, Object.keys, Object.getOwnPropertyNames all only look at the string-keyed properties. ES2015 added Reflect.ownKeys (which includes both strings and Symbols) and Object.getOwnPropertySymbols (which includes only own, Symbol-keyed properties).


Side note:

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

Not just objects, and it's more like String(d) (although if d is an object it comes to the same thing). Anything that isn't string or Symbol is converted to string.

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

Symbols aren't objects, Symbol is a primitive type. But yes, if the property key is a Symbol, it's used directly, not converted to string.



来源:https://stackoverflow.com/questions/59436684/javascript-computed-properties-deep-confusion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!