博主爲何要在繁忙的業務中抽時間寫這些最基本的筆記,就是想不斷積累本身小的細節,讓本身的開發更有效率,不能知其然不知因此然。javascript
博主在實際開發中使用了react全家桶(框架)+typescript(預編譯JS)+ES6(JS語法)+webpack(打包工具)+styledcomponent(css),並使用node模擬後臺數據。css
由於本身不想成爲寫業務 的機器, 而是致力成爲 技術 人員。html
ES6分類博文筆記摘自 http://es6.ruanyifeng.com/#docs/let java
博主在這裏只寫最核心和本身所須要的。node
let 命令react
let命令 用來聲明變量 ,與var的區別就是let所聲明 的變量 做用域只在let 命令所在的代碼塊{}有效,且須要先聲明後使用,若是直接使用會報錯webpack
a[i]()//這裏i從0到9都會打印10var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); };
a[i]();//這裏依次打印0到9 }
變量i
是var
聲明的,在全局範圍內都有效,因此全局只有一個變量i
。每一次循環,變量i
的值都會發生改變,es6
而循環內被賦給數組a
的function
在運行時,會經過閉包讀到這同一個變量i
,(其實我這裏也不是特別理解,得從新補習一下閉包)致使最後輸出的是最後一輪的i
的值,也就是10。web
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
變量i
是let
聲明的,當前的i
只在本輪循環有效,因此每一次循環的i
其實都是一個新的變量,因此最後輸出的是6
。你可能會問,若是每一輪循環的變量i
都是從新聲明的,那它怎麼知道上一輪循環的值,從而計算出本輪循環的值?這是由於 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變量i
時,就在上一輪循環的基礎上進行計算。 typescript
另外一個var和let的區別
var
命令會發生」變量提高「現象,即變量能夠在聲明以前使用,值爲undefined
。這種現象多多少少是有些奇怪的,按照通常的邏輯,變量應該在聲明語句以後纔可使用。
爲了糾正這種現象,let
命令改變了語法行爲,它所聲明的變量必定要在聲明後使用,不然報錯。(webstorm會自動檢測,而不是在編譯後檢測報錯,推薦使用)
// var 的狀況 console.log(foo); // 輸出undefined var foo = 2; // let 的狀況 console.log(bar); // 報錯ReferenceError let bar = 2;
上面代碼中,變量foo
用var
命令聲明,會發生變量提高,即腳本開始運行時,變量foo
已經存在了,可是沒有值,因此會輸出undefined
。變量bar
用let
命令聲明,不會發生變量提高。這表示在聲明它以前,變量bar
是不存在的,這時若是用到它,就會拋出一個錯誤。
這裏原博主說了不少,可是簡而言之就是若是在一個代碼塊中在let申明一個變量前使用了當前申請的變量,及時該變量已在外部聲明,即會拋出錯誤。
那有人會問了,既然拋出錯誤讓代碼不能執行,我平時用js都不會有這樣的問題,那我用let的意義在哪裏呢?
爲了讓你們養成良好的編程習慣,變量必定要在聲明以後使用,不然就報錯。
// 不報錯 var x = x; // 報錯 let x = x; // ReferenceError: x is not defined
上面代碼報錯,也是由於暫時性死區。使用let
聲明變量時,只要變量在尚未聲明完成前使用,就會報錯。上面這行就屬於這個狀況,在變量x
的聲明語句尚未執行完成前,就去取x
的值,致使報錯」x 未定義「。
ES6 規定暫時性死區和let
、const
語句不出現變量提高,主要是爲了減小運行時錯誤,防止在變量聲明前就使用這個變量,從而致使意料以外的行爲。這樣的錯誤在 ES5 是很常見的,如今有了這種規定,避免此類錯誤就很容易了。
let
不容許在相同做用域內,重複聲明同一個變量
ES5 只有全局做用域和函數做用域,沒有塊級做用域,這帶來不少不合理的場景。
第一種場景,內層變量可能會覆蓋外層變量。
var tmp = new Date(); function f() { console.log(tmp);//因爲下面變量提高,即會輸出undefined if (false) { var tmp = 'hello world';//沒有塊級做用域的限制,這裏聲明的tmp在ES5中會提高至函數做用域。雖然不會執行裏面的賦值,可是會變量提高 } } f(); // undefined
第二種場景,用來計數的循環變量泄露爲全局變量。
var s = 'hello'; for (var i = 0; i < s.length; i++) { console.log(s[i]); } console.log(i); // 5
上面代碼中,變量i
只用來控制循環,可是循環結束後,它並無消失,泄露成了全局變量。
let
實際上爲 JavaScript 新增了塊級做用域。
ES6 容許塊級做用域的任意嵌套。
if (true) { function f() {} } // 狀況二 try { function f() {} } catch(e) { // ... }
上面兩種函數聲明,根據 ES5 的規定都是非法的。
可是,瀏覽器沒有遵照這個規定,爲了兼容之前的舊代碼,仍是支持在塊級做用域之中聲明函數,所以上面兩種狀況實際都能運行,不會報錯。
ES6 引入了塊級做用域,明確容許在塊級做用域之中聲明函數。ES6 規定,塊級做用域之中,函數聲明語句的行爲相似於let
,在塊級做用域以外不可引用。
function f() { console.log('I am outside!'); } (function () { if (false) { // 重複聲明一次函數f function f() { console.log('I am inside!'); } } f(); }());
上面代碼在 ES5 中運行,會獲得「I am inside!」,由於在if
內聲明的函數f
會被提高到函數頭部,實際運行的代碼以下。
// ES5 環境 function f() { console.log('I am outside!'); } (function () { function f() { console.log('I am inside!'); } if (false) { } f(); }());
而在ES6中,因爲f()未聲明,因此會報錯
原來,若是改變了塊級做用域內聲明的函數的處理規則,顯然會對老代碼產生很大影響。爲了減輕所以產生的不兼容問題,ES6在附錄B裏面規定,瀏覽器的實現能夠不遵照上面的規定,有本身的行爲方式。
var
,即會提高到全局做用域或函數做用域的頭部。注意,上面三條規則只對 ES6 的瀏覽器實現有效,其餘環境的實現不用遵照,仍是將塊級做用域的函數聲明看成let
處理。
const
const也能夠用來申明變量 可是聲明的是常量。一旦聲明,常量的值就不能改變。
當咱們嘗試去改變用const聲明的常量時,瀏覽器就會報錯。const有一個很好的應用場景,就是當咱們引用第三方庫的時聲明的變量,用const來聲明能夠避免將來不當心重命名而致使出現bug: