JavaScriptに深く入る等しい操作子
4618 ワード
前に射雕英雄伝のブログで問題を見ましたが、中には次のようなコードがあります.
ECMAScriptには二つのタイプの等しい操作があることを知っています.フルタイムと不完全などを直接比較し、変換タイプ ではない.等しいかどうかは等しいです.まずタイプを変換してから を比較します.
合同と不完全の論理は比較的簡単ですが、今日は私たちが普段使っているのが多い第二の操作子です.私たちは二つの操作数を==で比較すると、二つの状況に分けます.タイプが違う場合はまずタイプを変える必要がありますが、その中の変換規則はどうなりますか?多くの人が詳しく研究したことがないかもしれません.今日は分析を通します.[]==[]の比較メカニズムを深く研究します.(一部の内容はルールのように「JavaScript高級プログラム設計(第二版)」から抜粋しています.)
一、両方のタイプが同じです.
両方のタイプが同じなら、比較のロジックは==と同じです.タイプが基本タイプであれば、その値を直接比較する .いずれも参照タイプであれば、その参照アドレス(同じオブジェクトを指すかどうか)を比較する .
以下のコードのように:
二、両側のタイプが違います.
==両方の操作数のタイプが違っている場合、同じタイプに操作数の種類を変換します.通常は強制的な変換とも言われています.操作数がブール値である場合、等しい値を比較する前に、それを数値falseに変換し、trueを1 に変換する.操作数が文字列である場合、もう一つの操作数が数値である場合、比較的等しい前に数値に変換します. 操作数がオブジェクト(参照タイプ)であり、他の操作数がそうでない場合は、オブジェクトのvalueOf()を呼び出し、得られた元の値を前の規則に従って比較する(元の値がオブジェクトである場合は元の値のtoString()を呼び出して再比較する) .
他にいくつか注意すべき点があります. nullとundefinedは等しい です.等しい値を比較する前に、nullとundefinedを他の値に変換することはできません(つまり、nullとundefined以外の値はnullとundefinedと同じではありません) 一般的に、a==bがtrueなら、a!bはfalseで、逆もいいですが、例外があります.それはNaNです.NaNは自分自身、つまりNaN=NaNとNaNを含めて、何の操作数にも等しくないです.NaNは全部false です.
以上の規則によって、私達は自分で比較的に等しい関数を書くことができます.
なぜですか[]=[]はtrueですか?その比較手順は以下の通りです.[]はfalseであり、式はfalse==[]に相当し、両方のタイプが異なり、オブジェクトがある[] 右側の[]valueOf()メソッドを呼び出しても、得られたのはオブジェクトであるため、toString()を再起動する方法は、ArayのtoString()メソッドはAray.join(')、例えば[1,2,3].tostring()は'1,2,3'に等しい. ブール値がfalseであるため、値0に変換し、式が0='' になる.最後に右側の空の文字列''をNumber()の方法で0に変えます.0==0はtrueです.だから![]==[] したがって、
if (![] == []) {
//Code
}
![]=[]、true or false?ECMAScriptには二つのタイプの等しい操作があることを知っています.
合同と不完全の論理は比較的簡単ですが、今日は私たちが普段使っているのが多い第二の操作子です.私たちは二つの操作数を==で比較すると、二つの状況に分けます.タイプが違う場合はまずタイプを変える必要がありますが、その中の変換規則はどうなりますか?多くの人が詳しく研究したことがないかもしれません.今日は分析を通します.[]==[]の比較メカニズムを深く研究します.(一部の内容はルールのように「JavaScript高級プログラム設計(第二版)」から抜粋しています.)
一、両方のタイプが同じです.
両方のタイプが同じなら、比較のロジックは==と同じです.
以下のコードのように:
console.log(5 == 5); //true
console.log('abc' == 'abc'); //true
console.log([] == []); //false,
var a = [], b = a;
console.log(a == b); //true
falseである以上、前の方がいいと言われるかもしれません.[]=[]の結果はtrueですよね?そうです.でも、その中の判断ロジックはそんなに簡単ではないです.falseに等しいので、この比較はfalse===[]に相当します.この時は両方のタイプが違っています.一つはBooleanで、一つはArayですので、簡単に[]=[]をfalseとして判断することはできません.[]=[]はtrueであり、[]を{}に置き換えると結果が違ってきます.console.log([] == []); //false
console.log(![] == []); //true
console.log({} == {}); //false
console.log(!{} == {}); //false
おバカになるかもしれませんが、同じ引用タイプなのに、なぜですか?[]==[]と{}={}の結果は違っていますか?それはArayが特別なところを持っているからです.この後は、まず両者のタイプが同じではない時の変換ルールを見に来ました.二、両側のタイプが違います.
==両方の操作数のタイプが違っている場合、同じタイプに操作数の種類を変換します.通常は強制的な変換とも言われています.
console.log(5 == '5'); //true, '5' 5
console.log(false == 0); //true, false 0
異なるデータタイプを変換する時、等しいかどうかは下記の基本ルールに従います.他にいくつか注意すべき点があります.
以上の規則によって、私達は自分で比較的に等しい関数を書くことができます.
function Equal(a, b) {
var typeA = typeof a, typeB = typeof b;
// NaN, false
//isNaN(undefined) true
if ((isNaN(a) && typeA === 'number') || (isNaN(b) && typeB === 'number')) { return false; }
// , ,
if (typeA === typeB) {
return a === b;
} else {
// undefined null( , )
if (typeA === 'undefined') { a = null; }
if (typeB === 'undefined') { b = null; }
if (a === null || b === null) {
return a === b;
} else if (typeA === 'object' || typeB === 'object') {
//
// valueOf , object, toString
var o = typeA === 'object' ? a : b, other = o === a ? b : a, ov = o.valueOf();
if (typeof ov === 'object') {
o = ov.toString();
}
return Equal(o, other);
} else {
// Boolean, Number
if (typeA === 'boolean') { a = a ? 1 : 0; }
if (typeB === 'boolean') { b = b ? 1 : 0; }
// Array, Number,Number() number NaN
if (typeA === 'string' && typeB === 'number') { a = Number(a); }
if (typeB === 'string' && typeA === 'number') { b = Number(b); }
return Equal(a, b);
}
}
}
console.log(Equal([], [])); //false
console.log(Equal(![], [])); //true
console.log(Equal({}, {})); //false
console.log(Equal(!{}, {})); //false
console.log(Equal(NaN, NaN)); //false
console.log(Equal(undefined, null)); //true
console.log(Equal(false, null)); //false
console.log(Equal(false, 0)); //true
console.log(Equal(true, 2)); //false
三、アラy.toString()なぜですか[]=[]はtrueですか?その比較手順は以下の通りです.
console.log(![] == []); //true
console.log(0 == []); //true
console.log(0 == ['']); //true
console.log('0' == []); //false
console.log('0' == [0]); //true
console.log(true == [1]); //true
まとめ:等しいと等しくない操作子にはタイプ変換の問題がありますので、コードの中のデータタイプの完全性を維持するために、全等と不全等の操作子を使用することを推奨します.