天天看點

ES6學習-let和const指令1.let指令2.塊級作用域3.const指令

說明:本文參考阮一峰的ECMAScript 6 入門

1.let指令

作用:let聲明的變量隻在其所在代碼塊内有效

{
	let a = 10
}
console.log(a )
           

代碼塊外使用會報錯: ReferenceError: a is not defined

for循環内使用let和var産生的不同效果:

下面代碼使用的是var,結果為10

var a = []
for (var i = 0; i < 10; i++) {
	a[i] = function () {
		console.log(i)
	}
}
a[9]() //10
           

上述代碼,因為變量i是var聲明的,在全局範圍内都有效,是以全局隻有一個變量i。這就導緻for循壞結束後i的值為10,而當我們再去調用a數組裡面的函數,函數裡面i的值即為i最終值10。

下面的代碼使用的是let,聲明的變量僅在塊級作用域内有效,最後結果為9

var a = []
for (let i=0; i < 10; i++) {
		a[i] = function () {
			console.log(i)
		}
	}
a[9]()//9
           

上述代碼,因為變量i是let聲明的,在塊級作用域内有效,就會導緻for循環的每一輪循環都會有自己聲明的變量i,可以了解為每輪循環都是在做以下的工作,隻不過各自的i值不同

當i=0時

{
	let i = 0
	a[i] = function () {
			console.log(i)
	}
}
           

當i=1時

{
	let i = 1
	a[i] = function () {
			console.log(i)
	}
}
           

等等…

當i=9時
{
	let i = 9
	a[i] = function () {
			console.log(i)
	}
}
           

當調用數組裡的函數,例如

a[9]()

,因為i在自己所聲明的代碼塊内有效,而函數和其同在一個代碼塊内,自然先找到自己所在代碼塊内的i,是以

a[9]()

輸出的值為9。

let指令不存在變量提升

var指令會發生“變量提升”現象,即變量可以在聲明之前使用,值為undefined

// var 的情況
console.log(a)   // 輸出undefined
var a = 10
// let 的情況
console.log(b) // 報錯ReferenceError
let b = 10
           

暫時性死區

隻要塊級作用域存在let聲明的變量,那麼這個變量就不再受外部影響

var temp = "abc"
if (true) {
	temp = "def" //ReferenceError: Cannot access 'tmp' before initialization
	let temp
}
           

上面代碼中,存在全局變量temp,if語句的代碼塊内也使用了let聲明的temp并且是在指派temp之後聲明的,但最終報錯是因為塊級作用域記憶體在let聲明的temp變量,使得該變量綁定在塊級作用域内,不會去尋找全局變量temp,而在let聲明之前就使用該變量就會報錯。

不允許重複聲明

let指令不允許在相同作用域内,重複聲明同一個變量,以下代碼會報錯

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

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

2.塊級作用域

ES5隻有全局作用域和函數作用域,沒有塊級作用域,這會導緻存在許多不合理場景。

例如記憶體變量覆寫了外層變量,for循壞的循環變量成為了全局作用域,循環結束後該循環變量依然存在不能被回收。

而ES6的let指令實際上就構成了塊級作用域。并且在ES6中規定允許在塊級作用域中聲明函數。

3.const指令

const指令用來聲明一個隻讀的常量,一旦聲明,常量的值就不能改變

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

上面代碼在試圖改變常量PI但報了錯

既然const聲明的變量不能進行改變,那麼就需要在聲明的時候進行初始化,不能留到以後再進行指派。

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

上面代碼說明const聲明變量時要進行初始化否則會報錯

const的作用域同let一樣,隻在聲明所在的塊級作用域内有效,const聲明的變量同let一樣不能重複聲明

if (true) {
  const MAX = 5;
}

MAX // Uncaught ReferenceError: MAX is not defined

           
//const聲明的變量同let一樣不能重複聲明
var msg= "Hello!";
let age = 19;

// 以下兩行都會報錯
const msg= "Goodbye!";
const age = 25;
           

const本質

const實際上是讓變量指向的記憶體位址儲存的資料不能改變,并不是變量的值不能改動。對于簡單類型(數值、字元串、布爾值)來說,值就儲存在變量指向的那個記憶體位址中,是以等同于常量。對于複雜類型(主要是對象和數組)來說,變量指向的記憶體位址儲存着指向實際資料的指針,const隻能保證這個指針是固定的,至于它指向的實際資料是否可變,則不受控制。是以在将一個對象聲明為常量值時,這個對象自身是可以改變的。

const person = {}
person.name = "王五"
person.name	//王五
person = {}  // TypeError: "person" is read-only
           

上面代碼person是一個常量對象,可以成功為其添加屬性name,但不能讓person重新指向另一個位址。

頂層對象的屬性

頂層對象,在浏覽器中是指window對象,在node中指global對象。在ES5中頂層對象的屬性與全局變量是等價的。

window.a = 1;
a // 1

a = 2;
window.a // 2
           

上面代碼中,頂層對象的屬性指派與全局變量的指派,是同一件事。

ES6中則規定,var指令和function指令聲明的全局變量依舊是頂層對象的屬性,而let、const、class指令聲明的全局變量不屬于頂層對象的屬性。

let a = 6
console.log(window.a) //undeined
           

上面代碼中,全局變量a由let指令聲明,是以它不是頂層對象的屬性,傳回undefined