ES6系列之聲明變量let與const

簡介

概念

ES6 的第一個版本,在 2015 年 6 月發佈了,正式名稱就是《ECMAScript 2015 標準》(簡稱 ES2015)。ES6 既是一個歷史名詞,也是一個泛指,含義是 5.1 版之後的 JavaScript 的下一代標準,涵蓋了 ES201五、ES201六、ES2017 等等,而 ES2015 則是正式名稱,特指該年發佈的正式版本的語言標準。
各大瀏覽器對ES6的支持:kangaxgit

Babel

Babel 是一個普遍使用的 ES6 轉碼器,能夠將 ES6 代碼轉爲 ES5 代碼,從而在現有環境執行。
Babel 的配置文件是.babelrc,存放在項目的根目錄下。使用 Babel 的第一步,就是配置這個文件。es6

聲明變量

ES5 只有兩種聲明變量的方法:var命令和function命令,ES6 除了添加let、const、import和class命令。因此,ES6 一共有 6 種聲明變量的方法。github

ES5 之中,頂層對象的屬性與全局變量是等價的。ES6 爲了改變這一點,一方面規定,爲了保持兼容性,var命令和function命令聲明的全局變量,依舊是頂層對象的屬性;另外一方面規定,let命令、const命令、class命令聲明的全局變量,不屬於頂層對象的屬性。也就是說,從 ES6 開始,全局變量將逐步與頂層對象的屬性脫鉤。

let

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

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

不容許重複聲明

let不容許在相同做用域內,重複聲明同一個變量。瀏覽器

// 報錯
function func() {
  let a = 10;
  var a = 1;
}

function func(arg) {
  let arg; // 報錯
}

function func(arg) {
  {
    let arg; // 不報錯
  }
}

塊級做用域

  • ES6 容許塊級做用域的任意嵌套。
  • 內層做用域能夠定義外層做用域的同名變量。
  • 外層做用域沒法讀取內層做用域的變量。
{{{{
  {let insane = 'Hello World'
   {let insane = 'Hello World'}
  }
  console.log(insane); // 報錯
}}}};

塊級做用域與函數聲明

  • ES5 規定,函數只能在頂層做用域和函數做用域之中聲明,不能在塊級做用域聲明。
  • ES6 規定,塊級做用域之中,函數聲明語句的行爲相似於let,在塊級做用域以外不可引用。

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

不存在變量提高

let命令所聲明的變量必定要在聲明後使用,不然報錯。數據結構

// var 的狀況
console.log(foo); // 輸出undefined
var foo = 2;

// let 的狀況
console.log(bar); // 報錯ReferenceError
let bar = 2;

暫時性死區

只要塊級做用域內存在let命令,它所聲明的變量就「綁定」(binding)這個區域,再也不受外部的影響。函數

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

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

const

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

  • 只在聲明所在的塊級做用域內有效。
  • const命令聲明的常量也是不提高,一樣存在暫時性死區,只能在聲明的位置後面使用。
const PI = 3.1415;
PI // 3.1415

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

本質

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;
相關文章
相關標籤/搜索