1. 程式人生 > >es5與es6的變數宣告和作用域的異同

es5與es6的變數宣告和作用域的異同

在es6沒出來之前,js的作用域只有兩種頂層作用域和函式作用域,但是es6的出現,讓js的變數作用域有了新的存在形式:塊級作用域

在瞭解塊級作用域之前,還是得先複習下es5的變數宣告與作用域

變數宣告:

我們都知道js使用var關鍵字來宣告一個變數,如果不使用var關鍵字來宣告變數就表示宣告的變數是頂層變數(雖然這不是一個嚴謹的寫法,在es5的嚴格模式下會丟擲異常)。當我們直接宣告一個變數的時候就相當於是在window下掛載了一個新變數。例如:

a = 1;
window.a = 1;
//上述兩種寫法是一樣的。但是在如下情況第一種寫法是錯誤的。

'use strict'
a = 1
; //Uncaught ReferenceError: a is not defined(…)

變數提升:

在js中所有由var宣告的變數都會提升到作用域的頂部進行宣告,然後再在宣告的地方進行賦值。還是直接看程式碼吧!

var a = 1;
function foo(){
    console.log(a);  //undefined;
    //因為該函式內重新聲明瞭一次a變數,雖然在當前語句的後面才a變數,但是變數宣告會被提升到當前函式作用域的頂部。
    //注意這裡只是將宣告提升到了頂部,而沒有進行賦值,賦值還是在宣告變數行進行,所有後面的console.log才會打印出3。
    var
a = 3; console.log(a); //3 } foo();

有一點需要注意的就是,var宣告函式變數時,和直接使用function定義函式時效果是不一樣的。var只能把變數名的宣告提前,而使用function定義函式時,函式的初始化也會被提前,所以不論你何時使用function宣告函式,只要有宣告呼叫時都不會產生錯誤,而使用var形式的函式表示式,在賦值之前呼叫都會找不到函式。

fun(); //Uncaught TypeError: fun is not a function(…)
var fun = function () {
    alert(1);
}

-----------
fun(); //1 function fun() { alert(1); }

還有一點就是重複使用同一函式名的兩個函式,後宣告的生效

function fun() {
    return 1;
}

console.log(fun());  //2

function fun() {
    return 2;
}

es6如何宣告變數:

es6引入了兩種新的宣告變數的方式:let與const。

  1. let
    使用let宣告的變數與var宣告的變數類似,唯一的區別就是隻能在當前塊級作用域中有用。先看看什麼是塊級作用域,所謂塊級作用域,就是當前的程式碼塊,簡單來說就是一對大括號中的內容就叫做塊級作用域,比如一個if語句中的內容,一個for迴圈中的內容。
{
    var  a = 1;
    let b = 2;
}

console.log(a); //1
console.log(b); //b is not defined(…)

再看一個例子:

if(true){
    let a = 1;
}

console.log(a); //a is not defined(…)

引入塊級作用域有很多好處,比如解決了之前for迴圈定義的變數造成全域性汙染的問題,而且不必再使用閉包來儲存必要的變數,因為各個程式碼塊的變數相互獨立,不會造成全域性變數的汙染。

//es5:
for(var i=0;i<5;i++){

}
console.log(i); //5


//es6:
for(let i=0;i<5;i++){

}
console.log(i); //i is not defined(…)
//es5:
var arr = []
for(var i=0;i<5;i++){
    arr[i] = function(){
        alert(i);
    }
}
arr[3](); //5


//es6:
let arr = []
for(let i=0;i<5;i++){
    arr[i] = function(){
        alert(i);
    }
}
arr[3](); //3
  1. const
    使用const宣告的變數與let宣告的變數類似,也只能在塊級作用域中有用,不同的是const宣告的變數是隻讀的,也就是宣告過後就不能被修改了。
const PI = 3.1415;
PI = 3; // Assignment to constant variable.

let與const沒有變數提升:

之前看到var宣告的變數都會提升到,但是使用let與const宣告的變數沒有這個特點。

{
    console.log(a); //a is not defined(…)
    let a = 1;

    -------

    console.log(b); //b is not defined(…)
    const b = 1;
}

如果在申明變數之前,就呼叫該變數就會產生錯誤(ReferenceError)。在上面的案例中let a之前我們呼叫了a變數,但是該變數是不可用的,我們把該變數不可用的區域叫做“暫時性死區”(temporal dead zone,簡稱TDZ)。這樣做也有好處,在沒有宣告變數之前就不能使用該變數從而可以減少一些程式碼執行的錯誤,像es5如果使用了也難以發現錯在哪裡。

不允許重複的變數宣告:

{
    let a = 1;
    let a = 2; //Identifier 'a' has already been declared
}

重複在同一個塊級作用域內宣告同一個變數會有語法錯誤。

es6為js的變數提供了兩種新的變數宣告方式(let與const),並且提供了新的塊級作用域。雖然這給之前js的靈活性帶來了一定的限制,但是這根本不算什麼,太靈活也會造成很多的混亂,塊級作用域的引入讓我們不必再使用閉包的方式來儲存一些變量了。

相關推薦

no