本文全部代碼都在 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
的返回值還不是基本數據類型,那麼就沒法比較了