ES6筆記之let聲明和const

博主爲何要在繁忙的業務中抽時間寫這些最基本的筆記,就是想不斷積累本身小的細節,讓本身的開發更有效率,不能知其然不知因此然。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 }

變量ivar聲明的,在全局範圍內都有效,因此全局只有一個變量i。每一次循環,變量i的值都會發生改變,es6

而循環內被賦給數組afunction在運行時,會經過閉包讀到這同一個變量i,(其實我這裏也不是特別理解,得從新補習一下閉包)致使最後輸出的是最後一輪的i的值,也就是10。web

  var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6

變量ilet聲明的,當前的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;

上面代碼中,變量foovar命令聲明,會發生變量提高,即腳本開始運行時,變量foo已經存在了,可是沒有值,因此會輸出undefined。變量barlet命令聲明,不會發生變量提高。這表示在聲明它以前,變量bar是不存在的,這時若是用到它,就會拋出一個錯誤。

暫時性死區

這裏原博主說了不少,可是簡而言之就是若是在一個代碼塊中在let申明一個變量前使用了當前申請的變量,及時該變量已在外部聲明,即會拋出錯誤。

那有人會問了,既然拋出錯誤讓代碼不能執行,我平時用js都不會有這樣的問題,那我用let的意義在哪裏呢?

爲了讓你們養成良好的編程習慣,變量必定要在聲明以後使用,不然就報錯。

// 不報錯 var x = x;  // 報錯 let x = x; // ReferenceError: x is not defined

上面代碼報錯,也是由於暫時性死區。使用let聲明變量時,只要變量在尚未聲明完成前使用,就會報錯。上面這行就屬於這個狀況,在變量x的聲明語句尚未執行完成前,就去取x的值,致使報錯」x 未定義「。

ES6 規定暫時性死區和letconst語句不出現變量提高,主要是爲了減小運行時錯誤,防止在變量聲明前就使用這個變量,從而致使意料以外的行爲。這樣的錯誤在 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只用來控制循環,可是循環結束後,它並無消失,泄露成了全局變量。

 

ES6 的塊級做用域

let實際上爲 JavaScript 新增了塊級做用域。

ES6 容許塊級做用域的任意嵌套。

塊級做用域與函數聲明(不理解也不要緊,本篇主要講解let)

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:

相關文章
相關標籤/搜索