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.
If you write it explicitly like that it's fairly useless, yes; but consider something like this:
letx={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.
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.
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.
Top comments (16)
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 aSymbol
. All three definitions above result in a theString
'1'
being used for the key since anything that isn't aSymbol
is coerced into aString
.Here's another one: Can you figure out what this expression will return?
It should be obvious what it does at face value, but can you tell for sure if that actually works without running it? ;)
return the index of the first element where there is no value present (undefined) in reverse order like 19..18..17...
This is why its the last index but internally the traversal is done from the reverse order
C
So, this works
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:
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}
andp
had a setter forx
, 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.
Can you show the code of the example?
I think it would be c but lets make it a little more interesting
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 beb
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.
c
, of course. All it does is write the same index three times, so the last value will be the final one.b