window.Objectのfalseのようなtrueの話
さて始まりました! HTMLファイ部の岩淵がお送りする、falseのようなtrueの話シリーズの第1弾です。 今回はObjectオブジェクトのお話です。
JavaScriptの不思議な振る舞いをクイズ形式で出題します。 みなさん、全問正解できるでしょうか!?
問1
({}) !== ({}); // == ?
解説:
オブジェクトは中身が同じでも、インスタンスとして違えば
別物とみなされます。
左辺と右辺それぞれのObject()のリテラル({}
)で別のインスタンスが生成されているので、同じように見えて等値ではありません。
値を比較しているというより、アドレスを比較していると考えた方がよいでしょう。
プリミティブと参照の違いはJavaScriptを扱う上で避けては通れません。
なお、
{} !== {};
そもそもこれは文法エラーになるので注意しましょう。
問2
var a = {};
var b = {};
a[window] = 5;
b[window] = 5;
a[window] === b[window]; // == ?
解説
まず注意。これを見て、「ハッシュのキーにオブジェクトを入れられるんだ!」と勘違いしてはいけません。
キーの値はいかなる場合も文字列として扱われるので、
キーはwindow
ではなくwindow.toString()
の返り値である'[object Window]'
が使われます(Google Chromeの場合)。
つまり、
var obj = {};
obj[window] = 5;
obj['[object Window]'] = 3;
obj[window]; // == 3
ほら、キーはwindowオブジェクトそのものではありません。
問3
var obj = {};
var obj = {};
obj[window] = 5;
obj.window = 3;
obj[window] !== obj.window; // == ?
解説
先ほどの問題と似ていますね。
このコードではブラケット表記とドット記法の2種類を使っています。
前者のobj[window]
は先ほど説明したとおりobj['[object Window]']
と書くのと同じですが、
後者のobj.window
はobj['window']
と書くのと同じです。
前者と後者でキー文字列が違うので、等値になりません。
問4
var a = {};
var b = {};
a[{}] = 5;
b[{}] = 5;
a[{}] === b[{}] // == ?
解説
これも第2問を理解していれば難しくありませんね。
({}).toString()
は(Google Chromeでは)'[object Object]'
を返すので、
a[{}]
はa['[object Object]']
と書くのと同じです。
a[{}]
とb[{}]
でObject()のリテラルが一時的に生成するオブジェクトは別のインスタンスですが、どちらも文字列に変換されるので結果的に同じキーになります
問5
!!(new Boolean(0)) // == ?
解説
Boolean(0)
の値はfalseですが、この問題のコードではBooleanオブジェクトのインスタンスを生成しています。
インスタンスはObject型のオブジェクトです。
つまり
typeof (new Boolean(0)) // == "object"
です。オブジェクトはtruthyな値なので、二重否定をしたらtrueになります。
問6
var obj1 = {a:5,b:3,c:8};
var obj2 = {b:3,a:5,c:8};
var keys1 = '';
var keys2 = '';
var i;
for(i in obj1) {
keys1 += i;
}
for(i in obj2) {
keys2 += i;
}
keys1 !== keys2 // == ?
解説
オブジェクトのキーはArrayと違って、キーの順番が関係ないと思っていませんか?
この問題のコードでは、オブジェクトのキーをfor文内で連結して、キーを文字列として連結しています。
obj1.d = 1;
のように後から追加したプロパティーは、末尾に追加されていきます。
また、obj1.a = 2;
のようにプロパティーを書き換えた場合は順番は変わらないようです。
ただし、この挙動はEcmaScriptの仕様上は保証されないので、あくまでもブラウザーの実装依存となります。
参考: オブジェクトのキーの順序 - hogehoge @teramako
あなたは何問正解できたでしょうか? これでJavaScriptの雑学が増えれば幸いです。
次回をお楽しみに。