if(a == 1 && a == 2 && a == 3){
console.log("我走進來了");
}
<!--答案1:-->
var a = {num:0};
a.valueOf = function(){
return ++a.num
}
<!--答案2:-->
var num = 1;
function a(){
return num++;
}
if(a() == 1 && a() == 2 && a() == 3){
console.log("我走進來了");
}
<!--答案3:-->
var num = 0;
Function.prototype.toString = function(){
return ++num;
}
function a(){}
<!--答案4:-->
var a = {[Symbol.toPrimitive]: ((i) => () => ++i) (0)};
複製程式碼
==
和===
寬鬆相等==
和嚴格相等===
都是來判斷兩個值是夠“相等”,但是他們有兩個有一個很重要的區別
==
允許在相等比較中進行強制型別轉換,而===
不允許
那麼這也是這道題之所以成為這道題的原因。
- 物件和非物件之間的相等比較
關於(物件/函式/陣列)和標量基本型別(字串/數字/布林值)之間相等比較,ES5有下面規定:
- 如果
Type(x)
是字串或數字,Type(y)
是物件,則返回x == ToPrimitive(y)
的結果; - 如果
Type(x)
是物件,Type(y)
是字串或數字,則返回ToPromitive(x) == y
的結果。
那麼ToPromitive操作是什麼呢?
物件(包括陣列)會轉換為相應的基本型別,
ToPromitive
會首先檢查該值是否有valueOf()
方法。如果有並返回基本型別值,就使用該值進行強制型別轉換。如果沒有就使用toString()
的返回值(如果存在)來進行強制型別轉換。如果
valueOf()
和toString()
均不返回基本型別值,會產生TypeError
錯誤。
那麼按照這個規則那麼答案一的原理就顯而易見了。
那麼按照這個規則下面程式碼也可以正常執行
var a = [3,4]
a.i = 0;
a.valueOf = function() {
return ++a.i
}
// 或者
// a.toString = function() {
// return ++a.i
// }
if(a == 1 && a == 2 && a == 3){
console.log("我走進來了");
}
複製程式碼
注意:陣列也是物件,所以也可以賦值屬性,所以a.i是正確的寫法,一般不推薦這麼做!!
- ++a, 和 a++
大家可以看到在答案一和答案二中有一個區別是 ++a
和 a++
那麼他們的初始值也是不一樣的,那麼這個是為什麼呢? 這個就要說到++a
和a++
的副作用了。
大部分的表示式是沒有副作用的,我們來看下下面的程式碼
function foo(){
a = a + 1
}
var a = 1
foo() // 結果值:undefined。副作用:a的值被改變
複製程式碼
再看
var a = 1
var b = a++
複製程式碼
a++
首先返回變數a
的當前值1,再將值賦值給b,然後將a
的值加1:
var a = 1
var b = a++
a // 2
b // 1
複製程式碼
看下面程式碼
var a = 1
a++ // 1
a // 2
++a // 3
a++ // 3
複製程式碼
++
在前面時,它的副作用產生在表示式返回結果之前,而a++
的副作用則產生在之後。
根據上面的這些原理,那麼也就解釋了num++
和a.num++
和為什麼他們的初始值不相同了。
Symbol.toPrimitive
這是超程式設計的裡面的東西。那麼什麼是超程式設計呢?
超程式設計是針對程式本身的行為進行操作的程式設計。換句話說,它是為你的程式的程式設計而進行的程式設計。
超程式設計關注幾點:程式碼檢視自己,程式碼修改自己,或者程式碼修改預設的語言行為而使其她程式碼受影響
那麼我們來看toPrimitive
== 操作符將在一個物件上不使用任何提示來呼叫ToPrimitive
操作--如果存在@@toPrimitive方法
的話,將使用default
被呼叫
Function.prototype.toString
由於原型鏈的關係,方法a(){}可以呼叫到Function上的toString()方法。 那當然下面的程式碼也可以使用開發中不要這麼做
var num = 0;
Object.prototype.toString = function(){
return ++num;
}
複製程式碼
以上就是這道題的原理解析,有什麼不同的錯誤請大家指正和提出意見建議。
希望大家知其然知其所以然,也希望社群裡關於這些題能給出更多的原理分析和解析,而不是簡單的寫出一個答案。
願世界和平!
封面: ColiN00B