在ECMAScript6(如下簡稱ES6)以前,ECMAScript的做用域只有兩種:node
一、 全局做用域;閉包
二、 函數做用域。ide
正是由於有這兩種做用域,因此在JavaScript中出現一術語--「變量提高(hoisting)」。函數
以下:spa
function func(){ console.log(test); var test = 1; }; func();
在node環境執行上述代碼,結果爲:3d
之因此爲’undefined’,緣由就在於‘變量提高’,在進入func函數時,將全部經過var聲明的變量置前並賦予undefined的值。code
但,ES6的到來,爲咱們提供了‘塊級做用域’。且‘塊級做用域’並不影響var聲明的變量。blog
What?‘塊級做用域’又不影響var聲明的變量?!!ip
是的,var聲明的變量的性質和原來同樣,仍是具備‘變量提高’的特性。而‘塊級做用域’經過新增命令let和const來體現。作用域
下面,咱們透過新增的let和const命令,協同感覺下ES6的塊級做用域。
注:因爲let和const屬於ES6,因此都必須使用嚴格模式,不然會報錯。
以下:
let test;
在node環境下,執行代碼:
2、let命令 |
什麼是let呢?
let和var差很少,都是用來聲明變量的。區別就在於:
一、 let聲明的變量只在所處於的塊級有效;
二、 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環境下,執行上述代碼結果以下:
3、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