Yes, c
- every subsequent property definition is overwriting the previous one.
For a little extra context here on why the overwriting occurs. Object keys can only be one of two things a String
or a Symbol
. All three definitions above result in a the String
'1'
being used for the key since anything that isn't a Symbol
is coerced into a String
.
I think it would be c but lets make it a little more interesting
const arrOrObj = [];
arrOrObj[1] = "a"
arrOrObj["1"] = "b"
// What is this?
console.log(arrOrObj["1"]);
Array indexe of 1 auto populates an array of length 2, does the string "1" go in the index or the object key value store?
Did you mean to leave x
unused, or is that a mistake in your example?
Either way, after line 3 the array [undefined, "b"]
so whether you index it with ["1"]
or with [x]
, the result is going to be b
Your right that x was unused, I've removed that. That's true, the reason I posted this is because arrays are slightly different from object bracket access.
but yes it's b
yes, result will be "c".
In JavaScript, object keys are internally converted to strings. In this case, all three property keys are essentially considered as the string "1". Since the last assignment to obj["1"] is "c", that value will be printed, resulting in "c" as the output.
So, this works
let x = {1: "a", 1: "b", 1: "c"}
console.log (x) -> { 1: 'c' }
I can hardly think of any situation where this behavior could be intended or even helpful. But, how to prevent this?
If you write it explicitly like that it's fairly useless, yes; but consider something like this:
let x = { foo: "fallback", ...defaults, bar: "override" }
Putting explicit properties on either side of the spread lets you establish whether the spread or the direct assignment takes precedence. Extending this behaviour to two explicit assignments to the same key only makes sense.
That being said, any linter worth its salt should detect code like that, because setting a variable twice explicitly is almost always unwanted, although I am not 100% sure if this is always superfluous.
So I was a bit curious what would happen if an object was defined like {__proto__: p, x: 1, x: 2}
and p
had a setter for x
, so I tested it real quick.
Turns out, even in that case, which is the only possible way I could think of to introduce side effects inside an object literal, JavaScript ignores the setter on the prototype and creates a data property on the new instance (which then also shadows the inherited accessor property from the prototype).
So no, as far as I can tell, a double assignment in an object literal will literally never have any semantic meaning.
c
, of course. All it does is write the same index three times, so the last value will be the final one.
Here's another one: Can you figure out what this expression will return?
Array.prototype.findLastIndex.call({length: 20}, value => value==undefined)
It should be obvious what it does at face value, but can you tell for sure if that actually works without running it? ;)
b