ES6知識整理(一)

ES6知識整理(一)

http://es6.ruanyifeng.com/

ES6簡介

ECMAScript 6.0,簡稱 ES6,是 JavaScript 語言的下一代標準,在 2015 年 6 月已經正式發佈。目標是使得 JavaScript 語言可以用來編寫複雜的大型應用程序,成爲企業級開發語言。

1、塊級作用域

1)爲什麼需要塊級作用域

ES5 只有全局作用域和函數作用域,沒有塊級作用域,這帶來很多不合理:

  • 內層變量可能會覆蓋外層變量。
  • 用來計數的循環變量泄露爲全局變量。

2)ES6 允許塊級作用域的任意嵌套。

外層作用域無法讀取內層作用域的變量。內層作用域可以定義外層作用域的同名變量。塊級作用域的出現,實際上使得獲得廣泛應用的立即執行函數表達式(IIFE)不再必要了。

3)塊級作用域與函數聲明

ES5 規定,函數只能在頂層作用域和函數作用域之中聲明,不能在塊級作用域聲明。ES6 引入了塊級作用域,明確允許在塊級作用域之中聲明函數。ES6 規定,塊級作用域之中,函數聲明語句的行爲類似於let,在塊級作用域之外不可引用。

如果改變了塊級作用域內聲明的函數的處理規則,顯然會對老代碼產生很大影響。爲了減輕因此產生的不兼容問題,ES6 在附錄B裏面規定,瀏覽器的實現可以不遵守上面的規定,有自己的行爲方式。

  • 允許在塊級作用域內聲明函數。
  • 函數聲明類似於var,即會提升到全局作用域或函數作用域的頭部。
  • 同時,函數聲明還會提升到所在的塊級作用域的頭部。

注意,上面三條規則只對 ES6 的瀏覽器實現有效,其他環境的實現不用遵守,還是將塊級作用域的函數聲明當作let處理。根據這三條規則,在瀏覽器的 ES6 環境中,塊級作用域內聲明的函數,行爲類似於var聲明的變量

考慮到環境導致的行爲差異太大,應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句。ES6 的塊級作用域允許聲明函數的規則,只在使用大括號的情況下成立,如果沒有使用大括號,就會報錯。

4)do 表達式

本質上,塊級作用域是一個語句,將多個操作封裝在一起,沒有返回值。現在有一個提案,使得塊級作用域可以變爲表達式,也就是說可以返回值,辦法就是在塊級作用域之前加上do,使它變爲do表達式,然後就會返回內部最後執行的表達式的值。
let x = do {
  let t = f();
};

2、let命令(let實際上爲 JavaScript 新增了塊級作用域。)

ES6 新增了let命令,用來聲明變量。它的用法類似於var,但是let所聲明的變量,只在let命令所在的代碼塊內有效,let聲明的變量只在它所在的代碼塊有效。

<script>
        function letCode(){
            let sum=0;
            for(let i=0;i<10;i++) {
                sum+=i;
                console.log(i);  
            }
            console.log(i);
        }
        letCode();
</script>
第一個console.log(i)輸出的結果是0,1,2,3,4,5,6,7,8,9
第二個console.log(i)輸出的結果是i is not defined
<script>
        function letCode(){
            var sum=0;
            for(var i=0;i<10;i++) {
                sum+=i;
                console.log(i);  
            }
            console.log(i);
        }
        letCode();
</script>
第一個console.log(i)輸出的結果是0,1,2,3,4,5,6,7,8,9
第二個console.log(i)輸出的結果是10

注意:for循環還有一個特別之處,就是設置循環變量的那部分是一個父作用域,而循環體內部是一個單獨的子作用域。

注意:1)let不存在變量提升

var命令會發生”變量提升“現象,let命令改變了語法行爲,所聲明的變量一定要在聲明後使用,否則報錯。
console.log(a);
var a=123;
console.log(b);
let b=234;
console.log(a)的結果是undefined,因爲發生了變量的提升,變量的聲明var a會提升,所以結果是undefined
console.log(b)的結果是b is not defined,let不存在變量提升現象

注意:2)會形成暫時性死區

只要塊級作用域內存在let命令,它所聲明的變量就“綁定”(binding)這個區域,不再受外部的影響。ES6 明確規定,如果區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。在代碼塊內,使用let命令聲明變量之前,該變量都是不可用的。這在語法上,稱爲“暫時性死區”(temporal dead zone,簡稱 TDZ)。使用let聲明變量時,只要變量在還沒有聲明完成前使用,就會報錯。在變量x的聲明語句還沒有執行完成前,就去取x的值,導致報錯”x 未定義“。比如:let x = x;結果就是x is not defined
tmp=123;
console.log(tmp);
打印的結果是123
tmp=123;
console.log(tmp);
let tmp;
console.log(tmp);
打印的結果是tmp is not defined,在let生命之前,都是tmp死區,只要用到這個變量就會報錯,在沒有let之前,typeof運算符是百分之百安全的。

ES6 規定暫時性死區和let、const語句不出現變量提升,主要是爲了減少運行時錯誤,防止在變量聲明前就使用這個變量,從而導致意料之外的行爲。這樣的錯誤在 ES5 是很常見的,現在有了這種規定,避免此類錯誤就很容易了。總之,暫時性死區的本質就是,只要一進入當前作用域,所要使用的變量就已經存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現,纔可以獲取和使用該變量。

注意:3)不允許重複聲明

let不允許在相同作用域內,重複聲明同一個變量。不能在函數內部重新聲明參數。

function repeat(){
        var a=1;
        let a=2;
        }
repeat();
結果是報錯,Uncaught SyntaxError: Identifier 'a' has already been declared
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章