es6-let和const

咱們知道es5中 var 聲明變量是做用於在全局或函數做用域,而且全局聲明的變量還會做爲 window 對象的屬性。這樣會增長程序錯誤的產生和不可控。es6

變量提高

在全局或者函數做用內用 var 聲明的變量,在js預編譯階段會提高到當前做用域的頂部,這就是變量提高。以下代碼:函數

function getValue(condition) {
  if (condition) {
    var value = 'red';
  } else {
    console.log(value); // undefined
  }
  console.log(value);  // undefined
}
複製代碼

以上代碼至關於把變量value放在當前做用域先聲明,因此才能在if塊外和else塊訪問到,都會輸出 undefinedpost

function getValue(condition) {
  var value;
  if (condition) {
    value = 'red';
  } else {
    console.log(value); // undefined
  }
  console.log(value);  // undefined
}
複製代碼

let聲明

從上面的能夠看出 var 聲明的變量沒有塊級做用域的概念,因此es6引入了let 聲明,並綁定在當前的塊做用域,塊做用域外訪問報錯,以下:ui

function getValue(condition) {
  if (condition) {
    let value = 'red';
  } else {
    console.log(value); // ReferenceError: value is not defined
  }
  console.log(value); // ReferenceError: value is not defined
}
複製代碼

禁止重複聲明。在同一個塊中不能用 let 聲明已經存在的標識符,不然會報錯。若是是嵌套的做用域中重複聲明,則不會報錯。es5

var count = 30;
let count = 30;  // SyntaxError: Identifier 'count' has already been declared

if (true) {
  let count = 30;  // 不會報錯
}
複製代碼

const聲明

在es6引入const 來進行常量的聲明。他和前面的 let 同樣有塊做用域綁定和不準重複聲明的特性。可是const 必需要在聲明的階段進行初始化,而let 不用。spa

let count;   // 不會報錯

const count;  //SyntaxError: Missing initializer in const declaration

const count = 30;  // 正確聲明
複製代碼

const 聲明的變量不能再賦值。若是變量是引用類型,能夠修改對象的屬性值,但不能夠從新修改綁定的對象。code

const count = 20;
count = 30;  // TypeError: Assignment to constant variable.

const obj = {};
obj.name = 'wozien';
複製代碼

臨時死區

因爲letconst 不存在變量提高,因此在聲明前使用該變量會報錯。由於在聲明前,該變量存在於所謂的臨時死區(TDZ)。對象

if (true) {
  console.log(typeof value);
  let value = 'red'; // ReferenceError: value is not defined
}
複製代碼

當變量聲明後,就會從臨時死區移出,後續可正常訪問。注意的是,TDZ是針對當前的塊做用域而言,因此以下能夠正確運行:作用域

console.log(typeof value); // undefiend
if (true) {
  let value = 'red';
}
複製代碼

在循環中的區別

var 聲明的循環變量,會在循環後外部可正常訪問,而且值爲跳出循環的值。let 聲明的變量則只在循環體內有效,以下:開發

for (var i = 0; i < 5; i++) {}
console.log(i); // 5

for (let i = 0; i < 5; i++) {}
console.log(i); // ReferenceError: i is not defined
複製代碼

在利用 var 聲明的循環中建立函數會變得很艱難,由於函數執行的時候是迭代完的最終,以下:

const func = [];
for (var i = 0; i < 3; i++) {
  func.push(() => {
    console.log(i);
  });
}
func.forEach(func => func()); // 2 2 2
複製代碼

咱們能夠利用當即執行函數(IIFE)解決這個問題,讓每一個函數最終保存的是迭代過程當中變量的副本。

for (var i = 0; i < 3; i++) {
  (function(value) {
    func.push(() => console.log(value));
  })(i);
}
複製代碼

在es6中循環裏面 let 聲明能夠用來簡化上面IIFE的實現過程,他會在每次迭代過程當中從新聲明一個同名變量i,值爲當前的迭代i的值,因此循環體內的函數使用的都是i值的副本。

for (let i = 0; i < 3; i++) {
  func.push(() => console.log(i));
}
func.forEach(func => func()); // 0 1 2
複製代碼

若是把 let 改爲 const, 在第二次迭代的時候會報錯,由於 const 不準從新賦值。而對於 for-infor-of 循環二者均可以正常的運行。

const obj = {
  a: 1,
  b: 2,
  c: 3
};
const func = [];

for (let key in obj) {
  func.push(() => console.log(key));
}

func.forEach(func => func());  // a b c
複製代碼

若是把let 替換成 var ,將會輸出3個c。由於 for-infor-of 每次都只會從新聲明一個新的副本key。

在全局中的綁定

利用 var 在全局聲明變量,會做爲window對象的一個屬性存在,而 letconst 則不會。

var a = 1;
let b = 2;
const c = 3;

console.log(window.a); // 1
console.log(window.b); // undefined
console.log(window.c); // undefined
複製代碼

小結

es6中的letconstvar 區別以下:

  • 綁定塊做用域,不存在變量提高
  • 不容許重複定義
  • 聲明前不容許使用變量
  • for 循環中每次建立新的副本
  • 全局聲明不做爲 window 屬性

在咱們平時的開發中,能夠默認使用const。在確認須要改變變量的值時才使用let,能夠必定程序上防止代碼的錯誤產生。

>>>原文地址

相關文章
相關標籤/搜索