若是你能確切的答出能夠,那恭喜你,你能夠繞道了git
有人會說,這個問題好奇葩,放在別的語言裏,這要是能輸出true,估計是見鬼了,可是你別說,放在js中好真有可能。最近在一我的的推特上提了一個問題:github
在這篇文章中,我將解釋這段代碼的原理:windows
const a = {
num: 0,
valueOf: function() {
return this.num += 1
}
};
const equality = (a==1 && a==2 && a==3);
console.log(equality); // true
複製代碼
你能夠打開chorme瀏覽器,而後打開開發者模式,在console中輸入這段代碼,你就能夠看到輸出結果([windows]: Ctrl + Shift + J [mac]: Cmd + Opt + J)瀏覽器
其實也沒有,能有的就是js中的兩個概念:函數
注意:這題裏面咱們用的是==而不是===,在js中==表明的是等於而不是全等,那麼就存在變量的隱式轉化問題。這就意味着結果會比咱們所指望的更多的可能性。對於js的隱式轉化,真的有不少文章,我推薦一下如下幾篇博客,若是你想要了解,能夠點進去:測試
推薦博客ui
JavaScript提供了一種將對象轉化爲原始值的方法:Object.prototype.valueOf(),默認狀況下,返回正在被調用的對象。this
咱們舉個例子:lua
const a = {
num: 0
}
複製代碼
咱們能夠對上述對象使用valueOf方法,他會返回一個對象。spa
a.valueOf();
// {num: 0}
複製代碼
是否是很酷,咱們能夠用typeOf來檢測一下這個輸出結果的類型:
typeof a.valueOf();
// "object"
複製代碼
爲了讓valueOf能夠更方便將一個對象轉化成原始值,咱們能夠重寫他,換種說法就是咱們能夠經過valueOf來返回一個字符串、數字、布爾值等來代替一個對象,咱們能夠看如下代碼:
a.valueOf = function() {
return this.num;
}
複製代碼
咱們已經重寫了原生的valueOf()方法,當咱們調用valueOf的時候,他會返回a.num。那咱們如今運行如下:
a.valueOf();
// 0
複製代碼
咱們獲得0了,這很合理,由於0就是賦給a.num的值。那咱們能夠來作幾個測試:
typeof a.valueOf();
// "number"
a.num == a.valueOf()
// true
複製代碼
很好,但爲何這個很重要呢?
這很重要,由於當你兩種不一樣類型的遇到相等操做符的時候,js會對其進行類型轉化——它企圖將操做數的類型轉化爲相似的。
在咱們的問題中:(a==1 && a==2 && a==3)
JavaScript會企圖將對象轉化成數字的類型,進行比較。當要轉化的是一個Object的時候,JavaScript會調用valueOf()方法。
自從咱們改變了valueOf()方法以後,咱們能不能作到如下幾點呢:
a == 0
// true
複製代碼
咱們作到了,異常輕鬆。
如今咱們須要作的的一點是:當咱們每次去調用a的值的時候,能改變它。
幸運的是,在JavaScript中有+=
符號。
+=
這個運算符能夠輕鬆的去改變一個的值,咱們能夠舉個簡單的例子:
let b = 1
console.log(b+=1); // 2
console.log(b+=1); // 3
console.log(b+=1); // 4
複製代碼
正如你所見的,咱們每次使用加法賦值運算符,可讓咱們的變量增長。
因此咱們能夠將這個觀念用到valueOf()中。
a.valueOf = function() {
return this.num += 1;
}
複製代碼
當咱們每次調用valueOf的時候,他會將變量增長1返回給咱們。
隨着這個改變,咱們來運行下面的代碼:
const equality = (a==1 && a==2 && a==3);
console.log(equality); // true
複製代碼
這就是它的工做原理。
記住下面兩點:
因此比較的時候咱們每次都能獲得true。
a == 1 ->
a.valueOf() == 1 ->
a.num += 1 == 1 ->
0 += 1 == 1 ->
1 == 1 -> true
a == 2 ->
a.valueOf() == 2 ->
a.num += 1 == 2 ->
1 += 1 == 2 ->
2 == 2 -> true
a == 3 ->
a.valueOf() == 3 ->
a.num += 1 == 3 ->
2 += 1 == 3 ->
3 == 3 -> true
複製代碼
謝謝你觀看這個小實驗,但願你能從中學到東西,有興趣的朋友也能夠去個人github點個star,你的支持是我持續輸出的動力,謝謝!!!