動畫:面試官問我 0.1 + 0.2 __ 0.3 ? 為什麼?該如何正確回答?

程式設計師小鹿發表於2019-10-10

寫在前邊

第一次去面試,面試官問我0.1 + 0,2 __ 0.3?估計很多人都知道在 JS 中0.1 + 0.2 != 0.3 的,至於大於還是小於還真沒弄明白。

像這種變態的問題,在 JS 中存在很多,那小鹿就乾脆整理成了一系列,希望對你的 JS 基礎進一步加牢,也希望你能在面試中順利拿到 offer。

1、學習困惑

我先談談我自己之前在方面遇到的困惑,學習 JS 很多基礎的知識起初不是那麼順利的,尤其是剛接觸 JS 的時候,因為 JS 歷史遺留了一些 bug,再加上它是弱型別語言,不像其它物件導向強型別語言很多概念一樣清晰。

2、學習建議

不建議在剛接觸就深入學習,很多知識知道這麼回事就可以,比如null為什麼通過 typeof 檢測為物件型別,一開始你只知道他通過 typeof 檢測為物件型別就可以。什麼時候去理解這些知識點的原理?

如果你覺得自己很懶,那就先不要去學習了,如果你對它的原理感興趣,自然而然你就學會探索了。但是,到了面試的時候,當面試官問到你這塊問題的時候,會遞迴式的問你了,到時候,你不得不去學原理了,這是你會發現,這些原理性的東西零散,這個人說東,那個人說西,然後我就根據優質的文章自己學習了下,整理成了一系列。

思維導圖

動畫:面試官問我 0.1 + 0.2 __ 0.3 ? 為什麼?該如何正確回答?

1、基本型別分類

JS 的基本型別分為兩大型別,分別為原始型別和物件型別。

原始型別包括哪些?物件型別包括哪些?為什麼要這樣分類?他們的區別又是什麼?

原始型別儲存的都是值,而物件型別儲存的都是地址。如下圖:

動畫:面試官問我 0.1 + 0.2 __ 0.3 ? 為什麼?該如何正確回答?

動畫:面試官問我 0.1 + 0.2 __ 0.3 ? 為什麼?該如何正確回答?

如上圖所示,我們清楚了原始型別和物件型別最根本的區別,那麼問題又來了,當我們進行變數之間賦值的時候,原始型別直接賦值的是值,而物件型別賦值的是地址。

動畫:面試官問我 0.1 + 0.2 __ 0.3 ? 為什麼?該如何正確回答?

動畫:面試官問我 0.1 + 0.2 __ 0.3 ? 為什麼?該如何正確回答?

所以,當我們將物件作為引數進行傳遞的時候,在函式內改變的是該地址指向的物件,而傳遞的引數是原始型別,則改變的是一個副本(複製的另一個值)。也就是說,如果是物件,則改變了原始的值,而不能改變原始型別原始的值。

原始型別共六種,分別為String、Number、Boolean、null、undefined、symbol

接下來對這六種原始型別中存在的問題我們逐一解決。

2、null

對於null有一個歷史存留的 bug,null是物件型別嗎?雖然我們使用 typeof 檢測null是物件型別,這其實是一個 bug。

2.1 原因是什麼?

因為 JS 最初的版本是 32 位系統的,為了將效能將用低位儲存變數型別資訊,000 開頭表示代表的是物件,此時null表示全零,所以系統就錯誤的將null判斷為物件型別。雖然 JS 內部判斷程式碼已經更改,但是這個 bug 一直留存下來。

2.2 null 出現的情況彙總

1、手動設定變數的值或者物件某一個屬性值為null(此時不賦值,後邊會賦值)。

2、在 JS 的 DOM 元素獲取中,如果沒有獲取到指定的元素物件,結果一般都是null。

3、Object.prototype._proto_的值也是null。

4、正則捕獲的時候,如果沒有獲取到結果,預設的也是null。

3、symbol

有關symbol使用的比較少,但是它的存在是有原因的。

3.1 symbol 是什麼?

symbol表示獨一無二的值,因為由於物件的屬性都是字串型別,我們避免不了相同字串衝突的問題。所以為了防止物件的屬性都是字串型別而衝突引入的。

3.2 symbol 的使用

 // 通常引數是字串型別,如果為物件型別,就會呼叫 toString 方法
 let s1 = Symbol(引數);// 這個引數可以認為是 Symbol 例項的一個描述,用於區分
 
 // 第一種寫法
 let a = {};
 a[s1] = 'Hello!';
 
 // 第二種寫法
 let a = {
    [s1] = 'Hello';
}
複製程式碼

4、undefined

4.1 undefined 出現的情況?

1、變數提升: 只宣告未定義預設值就是undefined。

2、嚴格模式下:沒有明確的執行主體,this就是undefined。

3、物件沒有這個屬性名,屬性值是undefined。

4、函式定義形參不傳值,預設就是undefined。

5、函式沒有返回值(沒有return或者return;),預設返回的就是 undefined。

5、為什麼 0.1 + 0.2 != 0.3 ?

上邊我們講了一些有關資料型別的坑,我們回過頭來,0.1 + 0.2 __ 0.3呢?為什麼會出現不相等的情況呢?面試該如何回答面試官?

5.1 是什麼導致了這種情況?

原因很簡單,JS 採用的是雙精度版本,這個版本就存在精度問題,就導致了上邊這種情況。

5.2 內部的原理是什麼?

我們計算機的資訊全部轉化為二進位制進行儲存的,那麼0.1的二進位制表示的是一個無限迴圈小數,該版本的 JS 採用的是浮點數標準需要對這種無限迴圈的二進位制進行擷取,從而導致了精度丟失,造成了0.1不再是0.1,擷取之後0.1變成了 0.100...001,0.2變成了0.200...002。所以兩者相加的數大於0.3。

那好,既然0.1不等於0.1了,那為什麼我在控制檯上輸出console.log(0.1)還等於0.1呢?

因為在輸入內容進行轉換的時候,二進位制轉換成十進位制,然後十進位制轉換成字串,在這個轉換的過程中發生了取近似值,所以列印出來的是一個近似值。

如果你把上邊的原理和麵試官一說,臥槽,面試官不給你 offer 都難,哈哈,開個玩笑,拿到 offer 不僅靠基礎,也要靠你的其他綜合能力。

小結

今天我們主要總結了一下有關 JS 基礎的知識點,雖然這些知識點比較坑,也比較雜,但是通過整理清晰了很多,文章中可能講的地方有問題,可以給小鹿指出。

這些不但是基礎,更是面試中最高頻面試官常常問到了,不同的公司面試官的問法也是大不相同,所以換湯不換藥,上邊總結的知識點也存在很多不足的地方,歡迎各位大佬補充。


❤️ 不要忘記留下你學習的腳印 [點贊 + 收藏 + 評論]

文章都看完了,為何不妨點個贊呢?嘻嘻,那就說明你很自私,你怕那麼好的文章讓別人也看到。開個小小玩笑。

其實我也很自私,我把我的一直以來堅持原創的公眾號:「小鹿動畫學程式設計」偷偷給你,裡邊匯聚了小鹿以動畫形式講解的資料結構與演算法、網路原理、Web 等技術文章。

動畫:面試官問我 0.1 + 0.2 __ 0.3 ? 為什麼?該如何正確回答?

作者Info:

【作者】:小鹿

【原創公眾號】小鹿動畫學程式設計

【簡介】:和小鹿同學一起用動畫的方式從零基礎學程式設計,將Web前端領域、資料結構與演算法、網路原理等通俗易懂的呈獻給小夥伴。公眾號回覆 “資料” 送一從零自學資料大禮包!

【轉載說明】:轉載請說明出處,謝謝合作!~

相關文章