1. 程式人生 > >ES6之塊級作用域

ES6之塊級作用域

c函數 說明 let和const 有變 代碼 正是 let -- [1]

一、前言

在ECMAScript6(以下簡稱ES6)之前,ECMAScript的作用域只有兩種:

  1、 全局作用域;

  2、 函數作用域。

正是因為有這兩種作用域,所以在JavaScript中出現一術語--“變量提升(hoisting)”。

如下:

技術分享圖片

在node環境執行上述代碼,結果為:

技術分享圖片

之所以為’undefined’,原因就在於‘變量提升’,在進入func函數時,將所有通過var聲明的變量置前並賦予undefined的值。

但,ES6的到來,為我們提供了‘塊級作用域’。且‘塊級作用域’並不影響var聲明的變量。

What?‘塊級作用域’又不影響var聲明的變量?!!

是的,var聲明的變量的性質和原來一樣,還是具有‘變量提升’的特性。而‘塊級作用域’通過新增命令let和const來體現。

下面,我們透過新增的let和const命令,協同感受下ES6的塊級作用域。

註:由於let和const屬於ES6,所以都必須使用嚴格模式,否則會報錯。

如下:

技術分享圖片

在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

ES6之塊級作用域