摘要:我們舉個例子我們可以對上述對象使用方法,他會返回一個對象。在我們的問題中會企圖將對象轉(zhuǎn)化成數(shù)字的類型,進行比較。幸運的是,在中有符號。當我們每次調(diào)用的時候,他會將變量增加返回給我們。
如果你能確切的答出可以,那恭喜你,你可以繞道了前言
有人會說,這個問題好奇葩,放在別的語言里,這要是能輸出true,估計是見鬼了,但是你別說,放在js中好真有可能。最近在一個人的推特上提了一個問題:
問題:Can (a==1 && a==2 && a==3) ever evaluate to true?
答案:yes
在這篇文章中,我將解釋這段代碼的原理:
const a = { num: 0, valueOf: function() { return this.num += 1 } }; const equality = (a==1 && a==2 && a==3); console.log(equality); // true
你可以打開chorme瀏覽器,然后打開開發(fā)者模式,在console中輸入這段代碼,你就可以看到輸出結(jié)果([windows]: Ctrl + Shift + J [mac]: Cmd + Opt + J)
有什么竅門呢?其實也沒有,能有的就是js中的兩個概念:
隱式轉(zhuǎn)換
object的valueOf函數(shù)
隱式轉(zhuǎn)換注意:這題里面我們用的是==而不是===,在js中==代表的是等于而不是全等,那么就存在變量的隱式轉(zhuǎn)化問題。這就意味著結(jié)果會比我們所期望的更多的可能性。對于js的隱式轉(zhuǎn)化,真的有很多文章,我推薦一下以下幾篇博客,如果你想要了解,可以點進去:
推薦博客
valueOfJavaScript提供了一種將對象轉(zhuǎn)化為原始值的方法:Object.prototype.valueOf(),默認情況下,返回正在被調(diào)用的對象。
我們舉個例子:
const a = { num: 0 }
我們可以對上述對象使用valueOf方法,他會返回一個對象。
a.valueOf(); // {num: 0}
是不是很酷,我們可以用typeOf來檢測一下這個輸出結(jié)果的類型:
typeof a.valueOf(); // "object"
為了讓valueOf可以更方便將一個對象轉(zhuǎn)化成原始值,我們可以重寫他,換種說法就是我們可以通過valueOf來返回一個字符串、數(shù)字、布爾值等來代替一個對象,我們可以看以下代碼:
a.valueOf = function() { return this.num; }
我們已經(jīng)重寫了原生的valueOf()方法,當我們調(diào)用valueOf的時候,他會返回a.num。那我們現(xiàn)在運行以下:
a.valueOf(); // 0
我們得到0了,這很合理,因為0就是賦給a.num的值。那我們可以來做幾個測試:
typeof a.valueOf(); // "number" a.num == a.valueOf() // true
很好,但為什么這個很重要呢?
這很重要,因為當你兩種不同類型的遇到相等操作符的時候,js會對其進行類型轉(zhuǎn)化——它企圖將操作數(shù)的類型轉(zhuǎn)化為類似的。
在我們的問題中:(a==1 && a==2 && a==3)JavaScript會企圖將對象轉(zhuǎn)化成數(shù)字的類型,進行比較。當要轉(zhuǎn)化的是一個Object的時候,JavaScript會調(diào)用valueOf()方法。
自從我們改變了valueOf()方法之后,我們能不能做到以下幾點呢:
a == 0 // true
我們做到了,異常輕松。
現(xiàn)在我們需要做的的一點是:當我們每次去調(diào)用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; }
當我們每次調(diào)用valueOf的時候,他會將變量增加1返回給我們。
隨著這個改變,我們來運行下面的代碼:
const equality = (a==1 && a==2 && a==3); console.log(equality); // true
這就是它的工作原理。
記住下面兩點:
使用相等操作符,js會做強制類型轉(zhuǎn)化
我們的對象每次調(diào)用valueOf()它的值會增加1
所以比較的時候我們每次都能得到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總結(jié)
謝謝你觀看這個小實驗,希望你能從中學到東西,有興趣的朋友也可以去我的github點個star,你的支持是我持續(xù)輸出的動力,謝謝!!!
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/92631.html
要是別人問您:如何讓 x 等于 1 且讓 x 等于 2 且讓 x 等于 3 的等式成立? 咋地,知道如何實現(xiàn)?想罵人有不 現(xiàn)在我們一起來分解思路: 我們先來講講寬松相等== 和嚴格相等 ===,這兩個都能用來判斷兩個值是否相等,但們明確上文提到的等于指的是哪一種,二者的區(qū)別看下: (1) 這兩個基礎直接的區(qū)別: (1.1) 不同類型間比較,== 比較轉(zhuǎn)化成同一類型后的值看值是否相等,...
我們說下想要實現(xiàn),一副牌里有54張,我們可以知道 3 - 2 的牌總共有13張,這分為4個花色是 ?? ?? ?? ?? 另外加上2個大小王!第一步:形成一個數(shù)組, 就要寫一個函數(shù),利用牌數(shù)量和花色,這樣可以用來形成一個雙重循環(huán)將 number 里面的內(nèi)容 和 flower 里面的內(nèi)容 進行一個循環(huán)嵌入?最后在用 push 生成一個對象放到數(shù)組的后面?再到最后放入 大小王 。 constnu...
今天主要就是匯總JavaScript數(shù)組的9中不同方法匯總,也將詳細示例展示給大家。 如果你還不知道數(shù)組實例中迭代方法有什么區(qū)別,可以看下面這張圖: map 代表返回一個新的數(shù)組,且數(shù)組中的每一項都是執(zhí)行過map提供的回調(diào)函數(shù)結(jié)果。 實現(xiàn)代碼如下: constmap=(array,fun)=>{ //類型約束 if(Object.prototype.toString.c...
Python Pampy是Python模式中一個比較常見的數(shù)據(jù)庫類型,它匹配到模式庫中的內(nèi)容還是比較的多的,代碼庫雖然只有150行,但是它的代碼是更加的簡潔的,能有效的提高我們的工作效率,那么,就具體的內(nèi)容,下面就給大家詳細解答下。 Pampy是哪路神仙 首先普及一下模式匹配。 模式匹配即給定某種模式,用這種模式去檢查序列或字符串是否符合這種模式,這種技術在自然語言處理中經(jīng)常使用。 P...
本篇文章主要是講述在JavaScript中判斷兩個值相等,不要認為很簡單,要注意的是在JavaScript中存在4種不同的相等邏輯。 ECMAScript 是 JavaScript 的語言規(guī)范,在ECMAScript 規(guī)范中存在四種相等算法,如下圖所示: 上圖中每個依次寫下來,很多前端應該熟悉嚴格相等和非嚴格相等,但對于同值零和同值卻不熟悉,現(xiàn)在就依次下面四種方法。 同值 同值零 非...
閱讀 1264·2021-11-17 09:33
閱讀 1728·2021-09-09 11:53
閱讀 3179·2021-09-04 16:45
閱讀 1357·2021-08-17 10:12
閱讀 2364·2019-08-30 15:55
閱讀 1770·2019-08-30 15:53
閱讀 2397·2019-08-30 15:52
閱讀 2549·2019-08-29 18:41