JavaScriptに深く入る等しい操作子

4618 ワード

前に射雕英雄伝のブログで問題を見ましたが、中には次のようなコードがあります.
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
    
    
    異なるデータタイプを変換する時、等しいかどうかは下記の基本ルールに従います.
  • 操作数がブール値である場合、等しい値を比較する前に、それを数値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
  • です.
    以上の規則によって、私達は自分で比較的に等しい関数を書くことができます.
    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ですか?その比較手順は以下の通りです.
  • []はfalseであり、式はfalse==[]に相当し、両方のタイプが異なり、オブジェクトがある[]
  • 右側の[]valueOf()メソッドを呼び出しても、得られたのはオブジェクトであるため、toString()を再起動する方法は、ArayのtoString()メソッドはAray.join(')、例えば[1,2,3].tostring()は'1,2,3'に等しい.
  • ブール値がfalseであるため、値0に変換し、式が0=''
  • になる.
  • 最後に右側の空の文字列''をNumber()の方法で0に変えます.0==0は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
    
    
    まとめ:等しいと等しくない操作子にはタイプ変換の問題がありますので、コードの中のデータタイプの完全性を維持するために、全等と不全等の操作子を使用することを推奨します.