ES6中提供了塊級作用域,分別是let和const,該隨筆分別介紹了它們 ...
一、前言 |
在ECMAScript6(以下簡稱ES6)之前,ECMAScript的作用域只有兩種:
1、 全局作用域;
2、 函數作用域。
正是因為有這兩種作用域,所以在JavaScript中出現一術語--“變數提升(hoisting)”。
如下:
function func(){ console.log(test); var test = 1; }; func();
在node環境執行上述代碼,結果為:
之所以為’undefined’,原因就在於‘變數提升’,在進入func函數時,將所有通過var聲明的變數置前並賦予undefined的值。
但,ES6的到來,為我們提供了‘塊級作用域’。且‘塊級作用域’並不影響var聲明的變數。
What?‘塊級作用域’又不影響var聲明的變數?!!
是的,var聲明的變數的性質和原來一樣,還是具有‘變數提升’的特性。而‘塊級作用域’通過新增命令let和const來體現。
下麵,我們透過新增的let和const命令,協同感受下ES6的塊級作用域。
註:由於let和const屬於ES6,所以都必須使用嚴格模式,否則會報錯。
如下:
let test;
在node環境下,執行代碼:
二、let命令 |
什麼是let呢?
let和var差不多,都是用來聲明變數的。區別就在於:
1、 let聲明的變數只在所處於的塊級有效;
2、 let沒有‘變數提升’的特性,而是‘暫時性死區(temporal dead zone)’特性。
下麵將一一講解。
1、let聲明的變數只在塊級有效。
如下:
'use strict'; function func(args){ if(true){ //let聲明i let i = 6; //在if內列印i值 console.log('inside: ' + i); } //在if外,再次列印i值 console.log('outside: ' + i); }; func();
在node環境中執行上述代碼,結果如下:
通過demo,我們可以清楚的看見,在第二次(if外)列印i值時,是報錯的。
這因為let聲明的變數i是屬於if內的塊級作用域;而不是像var一樣。
2、let沒有‘變數提升’的特性,而卻有‘暫時性死區(temporal dead zone)’的特性。
如下:
'use strict'; function func(){ //在let聲明前,列印i console.log(i); let i; }; func();
在node環境下執行上述代碼,結果如下:
在let聲明變數前,使用該變數,它是會報錯的,而不是像var那樣會‘變數提升’。
其實說let沒有‘變數提升’的特性,不太對。或者說它提升了,但是ES6規定了在let聲明變數前不能使用該變數。
如下:
'use strict'; var test = 1; function func(){ //列印test的值 console.log(test); let test = 2; }; func();
在node環境下執行上述代碼,結果如下:
如果let聲明的變數沒有變數提升,應該列印’1’(func函數外的test);而他卻報錯,說明它是提升了的,只是規定了不能在其聲明之前使用而已。我們稱這特性叫“暫時性死區(temporal dead zone)”。且這一特性,僅對遵循‘塊級作用域’的命令有效(let、const)。
關於let,最後再通過一個經典案例,體驗下。
如下:
var arr = []; for(var i = 0; i < 2; i++){ arr[i] = function(){ console.log(i); }; }; arr[1]();
arr[1]()會輸出2,原因是var聲明的變數會變數提升,且當執行arr[1]函數時,i取自於父函數的i,而此時i已經變為2了,所以就會列印2咯。
以前的常用做法是,利用閉包特性。如下:
var arr = []; for(var i = 0; i < 2; i++){ arr[i] = (function(i){ return function(){ console.log(i); }; }(i)); }; arr[1]();
又或者屬性方式:
var arr = []; for(var i = 0; i < 2; i++){ (arr[i] = function self(){ console.log(self.x); }).x = i; }; arr[1]();
現在有了let,它聲明的變數作用域為塊級,所以,我們也可以利用let來達到同樣的效果。
如下:
'use strict'; var arr = []; for(let i = 0; i < 2; i++){ arr[i] = function(){ console.log(i); }; }; arr[1]();
在node環境下,執行上述代碼結果如下:
三、const命令 |
const命令與let命令一樣,聲明的變數,其作用域都是塊級。
所以const遵循的規則與let相差無二,只是,const是用來聲明恆定變數的。
且,用const聲明恆定變數,聲明的同時就必須賦值,否則會報錯。
如下:
'use strict'; function func(){ const PI; PI = 3.14; console.log(PI); }; func();
在node環境下,執行上述代碼結果如下:
正確的方式為,聲明就得賦值。
如:
const PI = 3.14