javascript中的 ==

本文全部代碼都在 node v0.10.28 中測試經過,由於node用的也是v8的javascript引擎,因此理論上來講在chrome中的表現應該一致,其它引擎各位能夠本身測試javascript

準備工做

咱們先定義一個對象來進行比較java

?node

1
2
3
function foo() {
   this .name = "foo" ;
}

再定義一個函數來比對chrome

?函數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function compare(f) {
   console.log( "\ncompare with number:" );
   console.log( "number f == 1: %s" , f == 1 );
   console.log( "number f == 0: %s" , f == 0 );
 
   console.log( "\ncompare with string:" );
   console.log( "string f == \"\" : %s" , f == "" );
   console.log( "string f == \"foo\" : %s" , f == "foo" );
 
   console.log( "\ncompare with boolean:" );
   console.log( "boolean f == true : %s" , f == true );
   console.log( "boolean f == false : %s" , f == false );
 
   console.log( "\ncompare with object:" );
   console.log( "object f == {} : %s" , f == {});
}

第一次比較

?測試

1
compare( new foo());

輸出結果:this

?spa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
compare with number:
number f == 1 : false
number f == 0 : false
 
compare with string:
string f == "" : false
string f == "foo" : false
 
compare with boolean :
boolean f == true : false
boolean f == false : false
 
compare with object:
object f == {} : false

這個結果你們基本上都能理解.net

第二次比較

此次咱們給這個對象添加一個方法 valueOf 而後再來進行比較看看prototype

?

1
2
3
foo.prototype.valueOf  = function() {
     return 0 ;
};

?

1
compare( new foo());

結果爲:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
compare with number:
number f == 1 : false
number f == 0 : true
 
compare with string:
string f == "" : true
string f == "foo" : false
 
compare with boolean :
boolean f == true : false
boolean f == false : true
 
compare with object:
object f == {} : false

這個結果咱們發現

  • 和 0 比較

  • 和空字符串比較

  • 和false比較

這三種狀況返回 true

這個結果讓人很差理解
咱們在valueOf方法中加入一些輸出再來看看

?

1
2
3
4
foo.prototype.valueOf  = function() {
   console.log( 'valueOf: ' + this .name);
   return 0 ;
};

?

1
compare( new foo());

輸出結果爲:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
compare with number:
valueOf: foo
number f == 1 : false
valueOf: foo
number f == 0 : true
 
compare with string:
valueOf: foo
string f == "" : true
valueOf: foo
string f == "foo" : false
 
compare with boolean :
valueOf: foo
boolean f == true : false
valueOf: foo
boolean f == false : true
 
compare with object:
object f == {} : false

如今咱們能夠猜想一下了, javascript在進行對象和基本數據類型(暫且把string也當作一種基本數據類型,下面說基本數據類型的時候也會帶上string)比較的時候,會調用對象的valueOf方法的返回值來進行比較.

這樣就能夠解釋number比較中爲何和0比較是true了,
可是還有和空字符串比較是true,和false比較是true,這裏個人理解是 javascript在數字和字符串以及boolean進行比較的時候,會轉換成數字後進行比較,因此 0 == ""0 == false也是true

只有最後一個和對象比較的時候沒有打印 valueOf: foo 因此也能夠認爲是對象比較時,只比較引用地址,理論上來講,對象比較 == 和 === 應該是同樣的,例如以下代碼:

?

1
2
3
4
5
var b1 = new Boolean( false );
var b2 = new Boolean( false );
 
console.log(b1 == b2);
console.log(b1 === b2);

輸出兩次false

第三次比較

此次咱們將valueOf方法再修改一下,返回不是基本數據類型試一下,就返回本身吧

?

1
2
3
4
foo.prototype.valueOf  = function() {
     console.log( 'valueOf: ' + this .name);
     return this ;
};

?

1
compare( new foo());

輸出結果爲:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
compare with number:
valueOf: foo
number f == 1 : false
valueOf: foo
number f == 0 : false
 
compare with string:
valueOf: foo
string f == "" : false
valueOf: foo
string f == "foo" : false
 
compare with boolean :
valueOf: foo
boolean f == true : false
valueOf: foo
boolean f == false : false
 
compare with object:
object f == {} : false

此次和第一次比較沒什麼出入,只是打印了一些方法調用日誌而已,結果也理所固然的應該這樣了.

可是javascript爲何沒有遞歸調用咱們的valueOf方法呢,按道理咱們返回了本身,而後它進行比較的時候應該再次調用valueOf

此次咱們再加入一個toString方法來看看

?

1
2
3
4
foo.prototype.toString = function(){
     console.log( this .name + " : toString" );
     return this .name;
}

?

1
compare( new foo());

輸出結果爲:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
compare with number:
valueOf: foo
foo : toString
number f == 1 : false
valueOf: foo
foo : toString
number f == 0 : false
 
compare with string:
valueOf: foo
foo : toString
string f == "" : false
valueOf: foo
foo : toString
string f == "foo" : true
 
compare with boolean :
valueOf: foo
foo : toString
boolean f == true : false
valueOf: foo
foo : toString
boolean f == false : false
 
compare with object:
object f == {} : false

咱們發現每次輸出valueOf的後面都跟隨了一個toString的調用.

也就是說 javascript在調用valueOf後發現不是基本數據類型的時候,會調用toString的返回值再來進行比較
和咱們觀測到的結果一致,只有 f== "foo" 的結果是true

這樣也能夠解釋爲何沒有遞歸調用咱們的valueOf方法了

接下來咱們再狠一點,toString咱們也返回本身,看看javascript會怎麼處理

第四次比較

修改toString方法爲:

?

1
2
3
4
foo.prototype.toString = function(){
     console.log( this .name + " : toString" );
     return this ;
}

?

1
compare( new foo());

此次的結果會在乎料以外的:

結果爲:

?

1
2
3
4
5
6
7
8
9
10
11
12
console.log( "number f == 1: %s" , f == 1 );
                                      ^
TypeError: Cannot convert object to primitive value
     at compare (/home/ 0x0001 /Desktop/test.js: 25 : 38 )
     at Object.<anonymous> (/home/ 0x0001 /Desktop/test.js: 41 : 1 )
     at Module._compile (module.js: 456 : 26 )
     at Object.Module._extensions..js (module.js: 474 : 10 )
     at Module.load (module.js: 356 : 32 )
     at Function.Module._load (module.js: 312 : 12 )
     at Function.Module.runMain (module.js: 497 : 10 )
     at startup (node.js: 119 : 16 )
     at node.js: 906 : 3

結果報異常了

最後我以爲,javascript在將對象和基本數據類型進行比較的時候,會先調用valueOf的返回值來進行比較,若是valueOf返回的不是基本數據類型,那麼繼續調用toString方法的返回值來進行比較,
若是toString的返回值還不是基本數據類型,那麼就沒法比較了

相關文章
相關標籤/搜索