Posted at

JavaScript 忘れがちな === と == の違い

More than 3 years have passed since last update.

いつも何も考えずに==を使ってしまいがちですが、僕がずっと使っているIDE NetBeansでは、===を使えと警告してくれます。

この違いって何でしょうか?


==と===の違い

まず、文字と数値の比較実験

var a = "1";

var b = 1;

console.log(a==b);
結果:true
console.log(a===b);
結果:false

それぞれの演算子についてここで調べてみると、それぞれ機能が違うことがわかります。


== 等価演算子


数値と文字列を比較するとき、文字列は数値に変換されます。JavaScript は文字列の数値リテラルを Number 型の数値に変換しようと試みます。最初に、その文字列の数値リテラルから数学的な値を引き出します。次に、最も近い Number 型の値にこの値を丸めます。


つまり==は、文字列と数値の比較の場合、文字列を数値に変換してくれるわけです。


=== 厳密等価演算子


オペランド同士が、型を変換することなく(上に示した通り)厳密に等しいならば真を返します。


この場合、文字列は数値にに変換されないので、falseが返るわけです。


型変換について

等価演算子==では型変換が行われる場合があると説明しました。

型ていってもいろいろあるけど、どんな風に変換されるんでしょうか?


Boolean型


もしオペランドの片方が Boolean ならば、その論理オペランドは true ならば 1 に、そして false ならば +0 に変換されます。


console.log(true==1); // true

console.log(true===1); // false
console.log(false== 0); // true
console.log(false=== 0); //false


オブジェクト


オブジェクトを数値または文字列と比較する場合、JavaScript はそのオブジェクトの既定値を返そうとします。演算子はそのオブジェクトを、そのオブジェクトの valueOf や toString といったメソッドを用いて、プリミティブな値か、String か、あるいは Number の値に変換しようとします。そうした変換の試みが失敗したときにはランタイムエラーが生成されます。


console.log("foo" == new String("foo")); //true

console.log("foo" === new String("foo")); //false

上記は、プリミティブ型と、String型の比較であるため、String型がプリミティブに型変換してくれたわけです。

従って、下記はfalseです。

console.log(new String("foo")==new String("foo"));

異なるオブジェクト(というよりインスタンス)同士の比較になるため、falseになります。

ところで、こんないたずらするとどうなるか

var s = new String("foo");

console.log("foo"==s);//結果:true

//valueOfメソッドを書き換え
s.valueOf=function(){return "boo";}
console.log("foo"==s); //結果:false
console.log("boo"==s); //結果:true

String型とプリミティブ型の文字列を比較した場合、確かにvalueOfが呼ばれて、文字列と比較していることがわかります。

あと、undefinedとnullの比較をするとこうなります。

console.log(null == undefined);

結果:true
console.log(null === undefined);
結果:false


終わり

うまくまとめられないけど、名前の通り、

===のほうが厳密に比較してくれるってことです。