MDNのプロパティ名の説明がよくわからなかったので調べた

調べた元凶

ここの解説がいまいちよくわからない。

var foo = {unique_prop: 1}, bar = {unique_prop: 2}, object = {};  
object[foo] = 'value';  
console.log(object[bar]);  

foo と bar は同じ文字列に変換されるので、こちらも "value" を出力します。

えー・・・?違うオブジェクトを指定しているのに結果が同じってどういうこと?

検証

let hoge = 'foo', fuga = 'bar', piyo = {};  

piyo[hoge] = 'baz';  

console.log(piyo['foo']);  

console.log(piyo[hoge]);  

console.log(piyo[fuga]);  

オブジェクトでなく、ただの文字列にしてみる。

"baz"  
"baz"  
undefined  

piyo[fuga]、つまりpiyo['bar']undefinedになる。まあそりゃそうだ。

let hoge = {proc: 1}, fuga = {proc: 2}, obj = {};  

obj[hoge] = 'foo';  

console.log(obj[hoge]);  

console.log(obj[fuga]);  

次。hoge`とfuga`をオブジェクトにする。

"foo"  
"foo"  

やっぱり異なるオブジェクトを指定しても結果が一緒になる

let hoge = {proc1: 1}, fuga = {proc2: 1}, obj = {};  

obj[hoge] = 'foo';  

console.log(obj[hoge]);  

console.log(obj[fuga]);  

オブジェクトの内容を変えてみる。正確にはプロパティ名を変えて、値を同じにしてみる。

"foo"  
"foo"  

結果はやっぱり一緒。

結論

let hoge = {proc1: 1}, fuga = {proc2: 1}, obj = {};  

obj[hoge] = 'foo';  

console.log(obj[hoge]);  

console.log(obj[fuga]);  

console.log(String(hoge));  

console.log(String(fuga));  

console.log(obj["[object Object]"]);  

hogeおよびfugaというオブジェクトを、String()を使って強制的に文字列に変換してみる。

"foo"  
"foo"  
"[object Object]"  
"[object Object]"  
"foo"  

オブジェクトhogeを文字列に変換した結果は"[object Object]"。オブジェクトfugaを文字列に変換した結果も"[object Object]"。つまり、MDNの言う通り本当に「シンボル以外は強制的に文字列に変換」していることになる。

変換結果である、この"[object Object]"という「文字列」をプロパティ名として見ている。角カッコがあろうが空白があろうがお構いなし。なので、obj[hoge]と指定するとき、それはobj["[object Object]"]と指定しているのと同値になる。

property_nameは文字列またはシンボルです。この文字列は有効な識別子である必要はなく、任意の値、例えば "1foo", "!bar!", または " " (空白) であっても構いません。

いや、説明文には確かにそう書いてあるけどさ、乱暴すぎやしませんかね

まとめ

JavaScriptって、「!」みたいな記号でも何でも「文字は文字だろ?」って割り切った漢らしい(?)言語だってどっかで見た気がする。そのとおりだった。

JavaScriptって、いまいちよくわからない言語だなーと思ってたけどやっぱりよくわかない言語だと思います。