仍是先從一個題目開始:javascript
寫一個隔1s輸出數組的一項的函數。html
若是能夠用ES6語法,則能夠這麼寫:java
function print (arr) { for (let i = 0; i < arr.length; i++) { setTimeout(() => { console.log(arr[i]) }, 1000 * i); } }
可是若是把這裏的let
改爲var
,則輸出就會變成一連串的undefined
。react
有同窗很快想到了這是閉包啊,由於setTimeout
把函數加入到microqueue
中,因此等到setTimeout的函數體執行時,i
已經走完了for
循環,變成了arr.length
。arr[arr.length]
顯然是undefined。es6
簡單修改一下,變成ES5的語法。數組
function print (arr) { for (var i = 0; i < arr.length; i++) { (function (index) { setTimeout(() => { console.log(arr[index]) }, 1000 * index); })(i); } }
其實就是利用閉包是向父級做用域尋找值的特性,給i
包裝一層做用域,把i
存起來。babel
閉包概念還請翻看以前的一篇blog-閉包和類。閉包
到這裏閉包的理解應該差很少了,而今天的關鍵點在於——函數
阮一峯老師的《ECMAScript 6》入門裏給出[定義](http://es6.ruanyifeng.com/#docs/let:oop
ES6 新增了
let
命令,用來聲明變量。它的用法相似於var
,可是所聲明的變量,只在let
命令所在的代碼塊內有效。
他提到了let的幾個特性:
只存在於塊級做用域中
不存在變量提高
暫時性死區
不容許重複聲明
這裏我再也不贅述,你們能夠仔細閱讀一下阮一峯老師的書。
我更感興趣的是,在ES5的語法中,如何模擬let
這種塊級做用域的效果。這個時候,應該讓babel
出場了。
打開這個連接:能夠看到轉換後的代碼。
"use strict"; function print(arr) { var _loop = function _loop(i) { setTimeout(function () { console.log(arr[i]); }, 1000 * i); }; for (var i = 0; i < arr.length; i++) { _loop(i); } }
其實能夠對比發現,babel
轉換後的代碼和咱們上面寫的ES5實現實際上是同樣的。
大概就是經過對let
綁定的塊級做用域加一個函數,把let
聲明的參數,經過函數傳入,達到塊級做用域的效果。
你們能夠在babel
試一下let
的其餘特性,轉移出的ES5語法並不能實現有的特性,好比暫時性死區。
完,感謝閱讀。