ES6系列文章 塊級做用域

ES5以前javascript語言只有函數做用域和全局做用域,使用var來聲明變量,var聲明的變量還存在變量提高令人困惑不已。咱們先來複習一下ES5的var聲明,再對比學習let和const 。javascript

var

var聲明之函數做用域和全局做用域。

來段代碼體會一下:前端

function getName() {
    if (1 + 1 === 2) {
        var name = 'xixi';
    }

    console.log(name);
}

getName();//xixi

在c或java語言中name本應該只在if塊中使用的,可是在if的外面也能夠訪問到,這個就是 js沒有塊級做用域的一種體現。這個弊端在for循環中體現的十分明顯:java

for (var i = 0; i < 10; i ++) {
    // ...
}

console.log(i);// 10

var i的本意是聲明個臨時變量i,用來遍歷數組等,本不該該在for循環的外部訪問到,但如今卻能夠被訪問到你說鬧不鬧心?好一點的程序員會用當即執行函數來模擬塊級做用域,原來的我會注意一下儘可能不使用相同的變量名?。程序員

(function() {
    for (var i = 0; i < 10; i ++) {
        // ...
    }
})();

console.log(i);// undefined

以上:你們知道了 js 沒有塊級做用域。數組

變量能夠重複聲明

var name = 'xixi';
console.log(name);// xixi
var name= '一步';
console.log(name);// 一步

不報錯,困惑不困惑,這個就是變量能夠重複聲明。函數

變量提高

function getName() {
    console.log(name);
    var name = 'xixi';
    // ...
}

getName();// undefined

console.log打印name爲undefined。爲啥不報錯呢,對於一直使用js語言的人來講這個現象還好理解,若是是後臺轉前端的人來講估計得罵人了。這就是所謂的變量提高。簡單的向你們解釋一下吧。學習

var name = 'xixi';

這是一條被咱們寫爛了的語句,包含兩個過程:var name; name = 'xixi';分別爲變量聲明和變量初始化。spa

變量提高: 不管變量聲明var name;處於什麼位置,都會被提到做用域的頂部進行。code

let

ES6爲讓變量生命週期更加可控,引入兩個很是好的特性letconst。塊級做用域、不能重複聲明、臨時性死區等特性用來解決 var 變量存在的種種問題。對象

塊級做用域

function getName4ES6() {
    if (1 + 1 === 2) {
        let name = 'xixi';
    }

    console.log(name);
}

getName4ES6(); // undefined

終於在{}外面訪問不到name了。for循環也變的簡單了,你們試一下將for循環的var換成 let.

同一塊級做用域內不能重複聲明變量

function redefineValue() {
    let name = 'xixi';
    let name = '一步';
}

redefineValue();// Uncaught SyntaxError: Identifier 'name' has already been declared

重複聲明會報錯

{
    let name = 'xixi';
    console.log(name);// xixi
    {
        let name = 'yibu';
        console.log(name); // yibu
    }
}

注意: 在 ES6中,{}就是一個塊級做用域。

臨時性死區

function getName4ES6() {
    console.log(name);
    for (let i = 0; i < 10; i ++) {

    }
    let name = 'xixi';
    // ...
}

getName4ES6();// Uncaught ReferenceError: name is not defined

在上文ES5中,name還會存在變量提高,值爲undefined。ES6中又報錯了。怎麼解釋呢?。。。。這個就是臨時性死區的概念,在做用域塊中不能夠在變量聲明前就使用變量,若使用是會出錯的。

javascript引擎在發現變量聲明時,要麼將變量聲明提高到做用域的頂部(var聲明變量時),要麼將變量放在臨時性死區中(let、const聲明變量時),訪問臨時性死區中的變量會觸發運行時錯誤。

圖片描述

const

const和let一樣具備塊級做用域,不能重複聲明,臨時性死區的概念。它還具備兩個特有的特性:聲明的同時必須初始化、變量引用不能夠改變。

聲明的同時必須初始化

const name;//Uncaught SyntaxError: Missing initializer in const declaration

不賦值,就報錯。這個也很好理解const的本意就是用來定義常量,不可變的值。若不在聲明時給出初始值之後就再也沒有機會了。

值不可變

const name = 'x9x9';
name = 'yyy';// Uncaught SyntaxError: Invalid or unexpected token

那麼對象會怎樣呢?

const person = {
    name: 'lala',
    age: 40
};

person = {};// VM1042:6 Uncaught TypeError: Assignment to constant variable. at <anonymous>:6:8

引用是不可變的,那咱們在看看對象的屬性值是什麼狀況吧~

person.name = 'yoyo';
console.log(person);// {name: "yoyo", age: 40}

沒有報錯,對象引用不可改變,對象屬性能夠變動。

let vs const

你們可能會困惑,何時使用let,何時使用const。let能作的const好像均可以。網上有一種流行作法:能用const就毫不用let,簡單粗暴,不過很好用。我的見解:若變量在後續方法中會被改變,就使用let。一些常量聲明使用const, const聲明的變量名所有大寫。代碼中的變量,若是是let聲明的就表明其可變,如果const聲明的,不管是簡單數據類型仍是引用類型變量就都不要改變它的值。這樣,程序會更加的健壯,你們合做起來也比較方便。

相關文章
相關標籤/搜索