ES6入門筆記

本文參考阮一峯的ES6課程javascript

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

ES6 和 ES2015

2011 年,ECMAScript 5.1 版發佈後,就開始制定 6.0 版了。所以,ES6 這個詞的原意,就是指 JavaScript 語言的下一個版本。es6

ES6 的第一個版本,就這樣在 2015 年 6 月發佈了,正式名稱就是《ECMAScript 2015 標準》(簡稱 ES2015)。2016 年 6 月,小幅修訂的《ECMAScript 2016 標準》(簡稱 ES2016)如期發佈,這個版本能夠看做是 ES6.1 版,由於二者的差別很是小(只新增了數組實例的includes方法和指數運算符),基本上是同一個標準。根據計劃,2017 年 6 月發佈 ES2017 標準。數組

所以,ES6 既是一個歷史名詞,也是一個泛指,含義是 5.1 版之後的 JavaScript 的下一代標準,涵蓋了 ES201五、ES201六、ES2017 等等,而 ES2015 則是正式名稱,特指該年發佈的正式版本的語言標準。本書中提到 ES6 的地方,通常是指 ES2015 標準,但有時也是泛指「下一代 JavaScript 語言」。瀏覽器

let命令

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

/*=====================================*/
//example1
{
let a = 10;
var b = 1;
}

a // ReferenceError: a is not defined.
b // 1
/*=====================================*/
// example2
var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10
/*=====================================*/
var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6
複製代碼

var命令會發生「變量提高」現象,即變量能夠在聲明以前使用,值爲undefined; let命令改變了語法行爲,它所聲明的變量必定要在聲明後使用,不然報錯。
// var 的狀況
console.log(foo); // 輸出undefined
var foo = 2;

// let 的狀況
console.log(bar); // 報錯ReferenceError
let bar = 2; // 在這行以前的代碼塊內都屬於*暫時性死區*
複製代碼


ES6 明確規定,若是區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就造成了封閉做用域。凡是在聲明以前就使用這些變量,就會報錯。數據結構

總之,在代碼塊內,使用let命令聲明變量以前,該變量都是不可用的。這在語法上,稱爲「暫時性死區」(temporal dead zone,簡稱 TDZ)。函數

暫時性死區」也意味着typeof再也不是一個百分之百安全的操做。ui

下面代碼中,變量x使用let命令聲明,因此在聲明以前,都屬於x的「死區」,只要用到該變量就會報錯。所以,typeof運行時就會拋出一個ReferenceError。spa

做爲比較,若是一個變量根本沒有被聲明,使用typeof反而不會報錯。

typeof x; // ReferenceError
let x;

typeof undeclared_variable // "undefined"
複製代碼

let不容許在相同做用域內,重複聲明同一個變量。
// 報錯
function func() {
  let a = 10;
  var a = 1;
}

// 報錯
function func() {
  let a = 10;
  let a = 1;
}
複製代碼

ES6 引入了塊級做用域,明確容許在塊級做用域之中聲明函數。ES6 規定,塊級做用域之中,函數聲明語句的行爲相似於let,在塊級做用域以外不可引用。

但ES6 在附錄 B裏面規定,瀏覽器的實現能夠不遵照上面的規定,有本身的行爲方式。

  • 容許在塊級做用域內聲明函數。
  • 函數聲明相似於var,即會提高到全局做用域或函數做用域的頭部。
  • 同時,函數聲明還會提高到所在的塊級做用域的頭部。

注意,上面三條規則只對 ES6 的瀏覽器實現有效,其餘環境的實現不用遵照,仍是將塊級做用域的函數聲明看成let處理。

根據這三條規則,在瀏覽器的 ES6 環境中,塊級做用域內聲明的函數,行爲相似於var聲明的變量。

考慮到環境致使的行爲差別太大,應該避免在塊級做用域內聲明函數。若是確實須要,也應該寫成函數表達式,而不是函數聲明語句。

// 函數聲明語句
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 函數表達式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}
複製代碼

const命令

const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。

const聲明的變量不得改變值,這意味着,const一旦聲明變量,就必須當即初始化,不能留到之後賦值。

const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.

const foo;
// SyntaxError: Missing initializer in const declaration
複製代碼

const和let同樣做用於相同,只在聲明所在的塊狀做用域有效,並且存在暫時性死區

const實際上保證的,並非變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,所以等同於常量。但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const只能保證這個指針是固定的(即老是指向另外一個固定的地址),至於它指向的數據結構是否是可變的,就徹底不能控制了。所以,將一個對象聲明爲常量必須很是當心。

const foo = {};

// 爲 foo 添加一個屬性,能夠成功
foo.prop = 123;
foo.prop // 123

// 將 foo 指向另外一個對象,就會報錯
foo = {}; // TypeError: "foo" is read-only
複製代碼

可使用Object.freeze方法凍結對象

const foo = Object.freeze({});

// 常規模式時,下面一行不起做用;
// 嚴格模式時,該行會報錯
foo.prop = 123;

/*********一個將對象完全凍結的函數***********/
var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};
/*****************************************/
複製代碼

Summary

  • ES6指的是5.1 版之後的 JavaScript 的下一代標準,涵蓋了 ES201五、ES201六、ES2017 等等
  • ES6新增了let和const兩個命令
  • let和const都是隻在聲明所在的塊級做用域內有效
  • let和const都存在暫時性死區
  • let不存在變量提高,而var存在變量提高
  • const在聲明的時候必須賦值
  • const指向的值一旦聲明不可改變,對於const聲明的複合類型的值是可變的,不可變的是const聲明時所指向的數據地址
  • Object.freeze能夠凍結對象
相關文章
相關標籤/搜索