web-dev-qa-db-ja.com

JavaScript比較演算子:アイデンティティと同等性

私はJavaScriptの比較演算子の違い、つまり同一性と等価性の違いを理解しようと努めてきました。私が読んだことから、==を使用して2つのオブジェクトが等しいかどうかを確認すると、JavaScriptはそれらが同じ型であるかどうかを調べ、そうでない場合は同じ型に取得しようとします。ただし、===は同じように動作しません。例として:

var n = "1";
console.log(n==1);        // outputs true
console.log(n===1);       // outputs false

では、これらの「同一性」演算子と通常の等値演算子の違いは何ですか?両方を持っていることの利点は何ですか?

パフォーマンスに違いはありますか?アイデンティティー演算子は変換を行わないため、より高速になると思います。

また、配列などのより複雑なオブジェクトに関して、これらはどのように異なりますか?最も重要なのは、一方が他方よりも上で使用されるべき場合について、慣例は何と言っているのですか、なぜですか?

19
Hristo

等価演算子は、比較を行う前にデータ型を同じにしようとします。一方、アイデンティティ演算子では、両方のデータ型が前提条件と同じである必要があります。

この質問に似た投稿が他にもたくさんあります。見る:

PHP等号(==二重等号)と同一性(===トリプル等号)比較演算子はどのように異なりますか? (ニース比較チャートがあります)
どの等号演算子(== vs ===)をJavaScript比較で使用する必要がありますか?

実際には、ブール値がtrueまたはfalseであることを確認したい場合、識別演算子は非常に便利です...

1 == true     => true
true == true  => true
1 === true    => false
true === true => true
30

違いは、==、<=、> =および!=が型強制を行うことです。たとえば、文字列を数値として評価するように強制します。 ===、<==、> ==、および!==は型強制を行いません。それらは文字列を数値と比較し、文字列 "1"は数値1と同じではないため、結果はfalseになります。

参照はここにあります:
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Comparison_Operators

16
Joel Coehoorn

=====と同じですが、==が型変換を行う点が異なります

ここで私が何を意味するかを示すために、==とまったく同じように動作するJavaScript関数を示します。

// loseEqual() behaves just like `==`
function loseEqual(x, y) {
    // notice the function only uses "strict" operators 
    // like `===` and `!==` to do comparisons

    if(typeof y === typeof x) return y === x;

    if(typeof y === "function" || typeof x === "function") return false;

    // treat null and undefined the same
    var xIsNothing = (y === undefined) || (y === null);
    var yIsNothing = (x === undefined) || (x === null);

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);

    if(typeof x === "object") x = toPrimitive(x);
    if(typeof y === "object") y = toPrimitive(y);

    if(typeof y === typeof x) return y === x;

    // convert x and y into numbers if they are not already use the "+" trick
    if(typeof x !== "number") x = +x;
    if(typeof y !== "number") y = +y;

    return x === y;
}

function toPrimitive(obj) {
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();
}

この関数は、なぜ==を使用すべきでないと人々が言い続けるのかを説明するのに役立ちます。

ご覧のとおり、==には型変換のための複雑なロジックがたくさんあります。そのため、どのような結果が得られるかを予測することは難しく、バグにつながる可能性があります。

予期しない結果の例を以下に示します。

予期しない真実

[1] == true // returns true
'0' == false // returns true
[] == false // returns true
[[]] == false // returns true
[0] == false // returns true

'\r\n\t' == 0 // returns true

予期しない結論

// IF an empty string '' is equal to the number zero (0)
'' == 0 // return true

// AND the string zero '0' is equal to the number zero (0)
'0' == 0 // return true

// THEN an empty string must be equal to the string zero '0'
'' == '0' // returns **FALSE**

特別な機能を持つオブジェクト

// Below are examples of objects that
// implement `valueOf()` and `toString()`

var objTest = {
    toString: function() {
        return "test";
    }
};

var obj100 = {
    valueOf: function() {
        return 100;
    }
};

var objTest100 = {
    toString: function() {
        return "test";
    },
    valueOf: function() {
        return 100;
    }
};

objTest == "test" // returns true
obj100 == 100 // returns true
objTest100 == 100 // returns true

objTest100 == "test" // returns **FALSE**
10
Luis Perez

その理由は、アイデンティティまたは厳密な演算子(===)であり、タイプ変換なしと比較されます。つまり、両方の値が同じ値と同じタイプでない場合、それらは等しいとは見なされません。

次のリンクでより明確な説明:

https://medium.com/@ludico8/identity-vs-equality-battle-of-understanding-vs-758d396e922#.hhg396ey9

1
ludico8