ES6彙總(附加面試考點,冷知識點)————關於嚴謹性彙總(共2900+字)

前言

文章爲個人原創手寫,內容參考部分書籍(《深入理解ES6》)與博客(阮一峯),個人的彙總與總結。
如有不對,希望指出。

話題 鏈接
es6嚴謹性 https://juejin.im/post/5eea3020f265da02ab172265
es6簡潔性 https://juejin.im/post/5ef0116df265da02ba14e261
es6原對象方法的擴展 正在更新中
es6新概念的引入 正在更新中

ES6簡介

ES6,全稱ECMAScript 2015,於2015年發佈,成爲新一代前端標準。值得一提的是,當前的瀏覽器並不兼容ES6語法。我們需要藉助Babel去編譯。

ES6的重點

本人把ES6的改革從性質上分成四個部分,包括嚴謹性,簡潔性,原對象方法的擴展,以及新概念的引入

本文重點___嚴謹性

前端嚴謹性從發展角度越來越強。如後期的typescript更加明顯,由”弱語言“,逐步發展爲常規語言。ES6的更加嚴謹,可以從以下幾點進行分析。

塊級作用域

我們都知道,變量聲明(var)會有變量提升。這裏的變量會提前初始化,也可以提前訪問。當項目變量複雜的時候,很容易產生bug。es6就在這個時候,引入了let跟const。它解決了下邊的問題:

1)局部作用域
新引入的let,const聲明,再不會再產生變量提升。避免了變量提前訪問的場景,間接的提高了嚴謹性。我們可以在程序運行時就知道了報錯,而非後期的調試中。案例如下

alert("a=" + a);//此時a爲underfined,因爲變量a已提前聲明,但還未賦值
alert("b=" + b);//此時程序已拋出異常,因爲此時未找到變量b
var a = 1;
let b = 2;

2)禁止重複聲明
如果一個標識符已經在代碼塊內部被定義,那麼在此代碼塊內使用同一個標識符進行 let 聲明就會導致拋出錯誤。

3)區分常量與變量
這是let與const的區別。const 聲明會阻止對於變量綁定與變量自身值的修改,避免了我們日常開發中,了不小心改到常量的問題。

4)暫時性死區
用案例理解該概念。
for( var i = 0; i<10; i++ ){
setTimeOut( function(){
alert(i );
}, 1000);
}

for( let i = 0; i<10; i++ ){
    setTimeOut( function(){
        alert(i );
    }, 1000);
}

通過案例你可以發現,用var聲明的,會受setTimeOut所影響,
而let的沒有影響。可以說明let有暫時性死區。

冷知識

在 for-in與 for-of 循環中, let 與 const 都能在每一次迭代時創建一個新的綁定,這意味着在循
環體內創建的函數可以使用當前迭代所綁定的循環變量值
(而不是像使用 var 那樣,統一使用循環結束時的變量值)。
這一點在 for 循環中使用 let 聲明時也成立,不過在 for 循
環中使用 const 聲明則會導致錯誤。

面試考點

簡述var,let,const之間的區別?

參考答案:可參考上述解釋幾個要點。作用域,禁止聲明重複,區分常量與變量,暫時性死區。

需要理解,什麼是變量作用域的提升。


怎麼解決for循環延遲打印?如下案例,怎麼讓輸出正確的結果?
for( var i = 0; i<10; i++ ){
    setTimeOut( function(){
        alert(i );
    }, 1000);
}

參考答案:1.let聲明 2.利用閉包 3.立即執行函數

module模塊化

爲什麼要模塊化?
在以前,js一直沒有模塊化的體系。這就會產生一個問題,當項目到達大型時,很大可能性出現方法重疊,以及安全性問題,成爲大型項目的一個痛點與障礙。而es6模塊化正式爲此誕生。

冷知識

關於es6模塊化的冷知識:
  1. 模塊代碼自動運行在嚴格模式下,並且沒有任何辦法跳出嚴格模式
  2. 在模塊的頂級作用域創建的變量,不會被自動添加到共享的全局作用域,它們只會在模塊頂級作用域的內部存在;
  3. 模塊頂級作用域的 this 值爲 undefined ;
  4. 模塊不允許在代碼中使用 HTML 風格的註釋(這是 JS 來自於早期瀏覽器的歷史遺留特
    性);
  5. 對於需要讓模塊外部代碼訪問的內容,模塊必須導出它們;
  6. 允許模塊從其他模塊導入綁定。
  7. 模塊化可以用as重命名導出

面試考點

模塊化引入,跟常規js引入方法有什麼不同?

參考答案:

常規js引入,script標籤src爲"text/javascript"。
而如果你想直接引入模塊化js,則src="module"。
可能看到這裏,你會反駁,react跟vue打包編譯後,
他們模塊化後的代碼引入的script標籤,
爲什麼沒有用到src="module",
那是因爲人家已經經過webpack編譯後,
已經把你的模塊化代碼,打包成一個全局js文件中。

Web 瀏覽器中的模塊加載順序是怎麼樣的?

參考答案:

1)當使用模塊加載的時候,瀏覽器立即開始下載模塊文件,但並不會執行它,
直到整個網頁文檔全部解析完爲止。
(默認是defer,可以瞭解一下defer跟async的區別)
2)模塊執行的代碼,是由上往下的,如果中間包含內聯模塊,則會優先執行內鏈模塊

在es6模塊化之前,你還知道那些前端模塊化?他們之間有什麼區別?

參考答案:

在es6模塊化之前,社區還出現了一些模塊化的方法,
例如commonJS 和 AMD 。此外還有CMD。
下邊我們簡述一下他們的概念與區別。

1)AMD, commonJS, 與es6,都屬於預加載類型。而後期引入的CDM是懶加載。
    何爲預加載, 也就是說,在程序調用,所有的模塊都加載完成。
    而懶加載,是用到什麼的時候,纔去加載什麼。
2)AMD跟cmd專注於前端的規範。而commonjs跟es6 moudle可用於前後端。
3)AMD的代表做爲requirejs,cmd的代表作爲seajs。commonjs 與 es6,則無需引入,
    只需要引入編譯器(如babel)即可。 seajs爲淘寶引入的規範,我們都知道淘寶相對很大,
    不採用懶加載,首屏的時間將會很長,不過現在已經停止維護。
4)es6 跟 commonJS做了如下改變:
 1.ES6只能新增值,無法重新賦值就會報錯
 2.CommonJS 輸出是值的拷貝,即原來模塊中的值改變不會影響已經加載的該值,
    ES6靜態分析,動態引用,輸出的是值的引用,值改變,引用也改變
    ,即原來模塊中的值改變則該加載的值也改變。
 3.CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。
 4.CommonJS 加載的是整個模塊,即將所有的接口全部加載進來,
   ES6 可以單獨加載其中的某個接口(方法)。
 5.CommonJS this 指向當前模塊,ES6 this指向undefined

Symbol

Symbol個人也覺得是提高我們項目嚴謹性的方法之一。
它用於創建不可枚舉的屬性,並且這些屬性在不引用符號的情況下是無法訪問的。
只有在訪問屬性的時候用[]方法才能正確訪問,這算不算大大提高了我們程序的嚴謹性呢?

首先我們理解一下聲明是Symbol。Symbol是JS新引入的基本類型。我們都知道在ES5之前,JS 已有的基本類型(字符串、數值、布爾類型、 null 與 undefined )之外, ES6 引入
了一種新的基本類型。

思考一下,爲什麼要引入這個Symbol呢?

符號起初被設計用於創建對象私有成員,而這也
是 JS 開發者期待已久的特性。
在符號誕生之前,將字符串作爲屬性名稱導致屬性可以被輕易
訪問,無論命名規則如何。
而“私有名稱”意味着開發者可以創建非字符串類型的屬性名稱,由
此可以防止使用常規手段來探查這些名稱。

看到這裏,我們結合官方文檔。列舉一下Symbol常規作用。

應用場景

1.作爲內置屬性名稱

可觀察如下案例:

let name = Symbol();
let student = {};
person[name] = "weizhan";
console.log(person[name]); // "weizhan"

此代碼創建了一個符號類型的 name 變量,並將它作爲 student 對象的一個屬性,而每
次訪問該屬性都要使用這個符號值。
爲符號變量適當命名是個好主意,這樣你就可以很容易地說明它的含義。

它的好處就是可以避免同參數名的覆蓋。從這點,提高了程序的嚴謹性你是否贊同?因爲每一個Symbol都獨立存在,及時程序重名了,它也不會覆蓋。我們可以通過變量獲取它曾經覆過的值。

Symbol 作爲對象的屬性名,可以保證屬性不重名。
用Symbol只能用個[]去訪問,沒有其他方式可以進行訪問。

2.使用Symbol來替代常量

我們可以利用Symbol來創建一些常量。比如訂單狀態等。

const ORDER_RETRUN = Symbol();//訂單退貨狀態
const ORDER_SUCCESS = Symbol();訂單成功狀態
const ORDER_PAY = Symbol();//訂單支付狀態

這一點更體現出程序的簡潔性(下文)。如果沒有Symbol。
我們只能這樣去聲明。

const ORDER_RETRUN = "RETRUN";//訂單退貨狀態
const ORDER_SUCCESS = "SUCCESS";訂單成功狀態
const ORDER_PAY = "PAY";//訂單支付狀態

我們如果需要保證每個狀態都爲獨立存在,則要保證“RETRUN”,“SUCCESS”,“PAY”不一致。假設出現手誤
const ORDER_SUCCESS = “SUCCESS”;
const ORDER_PAY = “SUCCESS”;
兩者值都爲SUCCESS時,兩個狀態ORDER_SUCCESS跟ORDER_PAY則相等。跟我們原來的單一狀態設計相違背。而用Symbol()可直接獲取獨一無二的值。

看到這裏,是否覺得Symbol提高了嚴謹性。

冷知識點:

關於Symbol的一些額外api,筆者個人是不建議深入的。本文只是列舉,有興趣可自行查詢。

Symbol.hasInstance :供 instanceof 運算符使用的一個方法,用於判斷對象繼承關
系。
Symbol.isConcatSpreadable :一個布爾類型值,在集合對象作爲參數傳遞給
Array.prototype.concat() 方法時,指示是否要將該集合的元素扁平化。
Symbol.iterator :返回迭代器(參閱第七章)的一個方法。
Symbol.match :供 String.prototype.match() 函數使用的一個方法,用於比較字符串。
Symbol.replace :供 String.prototype.replace() 函數使用的一個方法,用於替換子字
符串。
Symbol.search :供 String.prototype.search() 函數使用的一個方法,用於定位子字符
第六章 符號與符號屬性
108
串。
Symbol.species :用於產生派生對象(參閱第八章)的構造器。
Symbol.split :供 String.prototype.split() 函數使用的一個方法,用於分割字符串。
Symbol.toPrimitive :返回對象所對應的基本類型值的一個方法。
Symbol.toStringTag :供 String.prototype.toString() 函數使用的一個方法,用於創建
對象的描述信息。
Symbol.unscopables :一個對象,該對象的屬性指示了哪些屬性名不允許被包含在
with 語句中。

面試考點

怎麼訪問到Symbol的值?

Symbol 值作爲屬性名時,該屬性是公有屬性不是私有屬性,可以在類的外部訪問。
但是不會出現在 for...in 、 for...of 的循環中
,也不會被 Object.keys() 、 Object.getOwnPropertyNames() 返回。
如果要讀取到一個對象的 Symbol 屬性,
可以通過 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。

Array

假設需要創建一個數組,傳統的new Array(2);第一個參數,可能爲數組長度,也可能是第一個參數值。
設計上沒有問題,但是程序中容易出現疏忽造成bug。

如果是克隆多一個數組呢?

而新引入數組方法,array.of跟array.form正是解決該問題。array詳細部分,會在第三篇文章具體列出。

es6嚴謹性 : https://juejin.im/post/5eea3020f265da02ab172265

es6簡潔性 : https://juejin.im/post/5ef0116df265da02ba14e261

es6原對象方法的擴展: https://juejin.im/post/5ef0116df265da02ba14e261

es6新概念的引入: 正在更新中

友情提示

該文章已結束,下一篇文章,關於es6簡潔性彙總,主要知識點包括:
字符串模版,箭頭函數,class的引入,解構函數的引入,js原型擴展等。

https://juejin.im/post/5ef0116df265da02ba14e261

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章