重學前端-模塊一Javascript 1-9講

關於類型的細節

關於Javascript的類型,各種文檔介紹的已經很全面了,也是前端開發人員最熟悉的概念之一,但如果對下面的幾個問題還有猶豫,說明對於類型這部分知識點,還是有遺漏部分的。

爲什麼有的編程規範要求用 void 0 代替 undefined?

字符串有最大長度嗎?

String有最大長度2^53-1,但是這個所謂的最大長度並不是字符數。
String的意義並非“字符串”,而是字符串的UTF16編碼,字符串操作charAt, charCodeAt, length等方法針對的都是UTF16編碼,所以字符串的最大長度,實際上是受字符串的編碼長度影響的。
JavaScript 中的字符串是永遠無法變更的,一旦字符串構造出來,無法用任何方式改變字符串的內容,所以字符串具有值類型的特徵。

0.1 + 0.2 ≠ 0.3 ?

Javascript的Number類型表示通常意義上的“數字”。大致對應數學中的有理數,但是計算機有精度限制。
avaScript 中的 Number 類型基本符合 IEEE 754-2008 規定的雙精度浮點數規則。(Javascript並未定義不同類型的數字數據類型,而是始終將數字存儲爲雙精度浮點值)
根據雙精度浮點數的定義,Number 類型中有效的整數範圍是 -0x1fffffffffffff 至 0x1fffffffffffff,所以 Number 無法精確表示此範圍外的整數。
同樣根據浮點數的定義,非整數的 Number 類型無法用 ===== 也不行) 來比較。

console.log( 0.1 + 0.2 == 0.3); //false

對於計算機而言,兩個數字在相加時是以二進制形式進行的,在呈現結果時才轉換成十進制。所以在計算0.1+0.2時,會先把兩個數字轉換爲二進制數字,轉二進制的時候如果尾數的52位不能完全滿足,只會達到要求的精度。

// 0.1 轉化爲二進制
0.0 0011 0011 0011 0011...(0011無限循環)
// 0.2 轉化爲二進制
0.0011 0011 0011 0011 0011...(0011無限循環)
//由於雙精度表示法的尾數只有52位,0.1和0.2轉換後的值爲
e = -4; m =1.1001100110011001100110011001100110011001100110011010 (52)
e = -3; m =1.1001100110011001100110011001100110011001100110011010 (52)

兩個二進制相加的結果爲:

//相加時如果指數不一致,需要對齊,一般情況下是向右移,因爲最右邊的即使溢出了,損失的精度遠遠小於左邊溢出。
  (e = -3; m = 0.1100110011001100110011001100110011001100110011001101)
  + (e = -3; m = 1.1001100110011001100110011001100110011001100110011010)

=  (e = -3; m = 10.0110011001100110011001100110011001100110011001100111)
=  (e = -2; m = 1.0011001100110011001100110011001100110011001100110100)
= 0.010011001100110011001100110011001100110011001100110100
= 0.30000000000000004  //(十進制)

浮點數運算的精度問題導致等式左右的結果並不是嚴格相等,而是相差了個微小的值0.300000000000000040.3
用Javascript提供的最小精度值比較可得到結果爲true

console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);

ES6 新加入的 Symbol 是個什麼東西?

Symbol 是 ES6 中引入的新類型,它是一切非字符串的對象 key 的集合,在 ES6 規範中,整個對象系統被用 Symbol 重塑。Symbol 可以創建一個獨一無二的值(但並不是字符串)。
Symbol 可以具有字符串類型的描述,但是即使描述相同,Symbol 也不相等。
創建Symbol的方式是使用全局的Symbol函數。

var mySymbol = Symbol("my symbol");

爲什麼給對象添加的方法能用在基本類型上?

在Javascript中,對象的定義是“屬性的集合”,屬性分爲數據屬性和訪問器屬性,二者都是key-value結構,key可以是字符串或Symbol類型。
Javascript的基本類型,都在對象類型中有一個“親戚”,分別是Number,String,Boolean,Symbol,所以3new Number(3)是完全不同的值,一個是Number類型,一個時對象類型。
Javascript的.運算符提供了裝箱操作,會根據基礎類型構造一個臨時的對象,使得我們能在基礎類型上調用對應對象的方法。
所謂裝箱轉換,就是把基本類型轉換爲對應的對象,它是類型轉換中相當重要的種類。

Javascript對象

對 JavaScript 來說,屬性並非只是簡單的名稱和值,JavaScript 用一組特徵(attribute)來描述屬性(property)。
數據屬性:
它比較接近於其它語言的屬性概念。數據屬性具有四個特徵。

  • value:就是屬性的值。
  • writable:決定屬性能否被賦值。
  • enumerable:決定 for in 能否枚舉該屬性
  • configurable:決定該屬性能否被刪除或者改變特徵值。在大多數情況下,我們只關心數據屬性的值即可。第
    訪問器(getter/setter)屬性,它也有四個特徵:
  • getter:函數或 undefined,在取屬性值時被調用
  • setter:函數或 undefined,在設置屬性值時被調用
  • enumerable:決定 for in 能否枚舉該屬性
  • configurable:決定該屬性能否被刪除或者改變特徵值。
    Javascript的對象分爲幾類:
  • 宿主對象(host Objects):由 JavaScript 宿主環境提供的對象,它們的行爲完全由宿主環境決定。(如window對象)
    • 內置對象(Built-in Objects):由 JavaScript 語言提供的對象。
    • 固有對象(Intrinsic Objects ):由標準規定,隨着 JavaScript 運行時創建而自動創建的對象實例。
    • 原生對象(Native Objects):可以由用戶通過 Array、RegExp 等內置構造器或者特殊語法創建的對象。
    • 普通對象(Ordinary Objects):由{}語法、Object 構造器或者 class 關鍵字定義類創建的對象,它能夠被原型繼承。

Javascript執行

異步執行的順序:

  • 首先我們分析有多少個宏任務;
  • 在每個宏任務中,分析有多少個微任務;
  • 根據調用次序,確定宏任務中的微任務執行次序;
  • 根據宏任務的觸發規則和調用次序,確定宏任務的執行次序;
  • 確定整個順序。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章