ES6-新的變量聲明方式(2)

在ES5中,變量聲明只有var和function以及隱式聲明三種,在ES6中則增長了let、const、import和class四種。node

1. letjquery

1.1 塊級做用域面試

let聲明的變量的做用域是塊級做用域(這個特性有點相似於後臺語言),ES5 並無塊級做用域,只有函數做用域和全局做用域。數組

{
  let a = 'ES6';
  var b = 'ES5';
}

console.log(b)  // ES5 
console.log(a)  // ReferenceError: a is not defined.

那麼let的塊級做用域有什麼好處呢?數據結構

let很是適合用於 for循環內部的塊級做用域。JS中的for循環體比較特殊,每次執行都是一個全新的獨立的塊做用域,用let聲明的變量傳入到 for循環體的做用域後,不會發生改變,不受外界的影響。看一個常見的面試題目:異步

for (var i = 0; i <10; i++) {  
  setTimeout(function() {  // 同步註冊回調函數到異步的宏任務隊列。
    console.log(i);        // 執行此代碼時,同步代碼for循環已經執行完成
  }, 0);
}
// 輸出結果
10   (共10個)
// 這裏變量爲i的for循環中,i是一個全局變量,在全局範圍內都有效,因此每一次循環,新的i值都會覆蓋舊值,致使最後輸出的是最後一輪i的值,即i的最終結果爲10,實際上都是console.log(10)。涉及的知識點:JS的事件循環機制,setTimeout的機制等

把 var改爲 let聲明:函數

for (let i = 0; i < 10; i++) { 
  setTimeout(function() {
    console.log(i);    //當前的i僅在本輪的循環中有效,就是說每一次循環,i其實都是一個新產生的變量。                          //用 let 聲明的變量 i 只做用於循環體內部,不受外界干擾。
  }, 0);
}
// 輸出結果:
0  1  2  3  4  5  6  7  8 9

1.2 暫時性死區(Temporal Dead Zone)ui

在一個塊級做用域中,變量惟一存在,一旦在塊級做用域中用let聲明瞭一個變量,那麼這個變量就惟一屬於這個塊級做用域,不受外部變量的影響,以下面所示。this

var tmp = 'bread and dream';
if(true){
    tmp = 'dream or bread';   //ReferenceError
    let tmp;
}

這個例子中tmp = 'dream or bread'的賦值會報錯,由於在if塊中的let對tmp變量進行了聲明,致使該tmp綁定了這個做用域,而let臨時死區致使了並不能在聲明前使用,因此在聲明前對變量賦值會報錯。prototype

暫時性死區的本質就是,只要一進入當前做用域,所要使用的變量就已經存在了,可是不可獲取,只有等到聲明變量的那一行代碼出現,才能夠獲取和使用該變量。

暫時性死區的意義也是讓咱們標準化代碼,將全部變量的聲明放在做用域的最開始。

1.3 不容許重複聲明

(1) 在相同的做用域內,用let聲明變量時,只容許聲明一遍,但 var是能夠屢次聲明的。你們都知道ES5 屢次聲明會形成變量覆蓋並且不會報錯,這就給調試增長了難度,而let可以直接扼殺這個問題在搖籃之中,由於會直接報錯。

// 不報錯
function demo() {
  var a = 'bread and dream';
  var a = 'dream or bread';
}
 
// 報錯,Duplicate declaration "a"
function demo() {
  let a = 'bread and dream';
  var a = 'dream or bread';
}

// 報錯,Duplicate declaration "a"
function demo() {
  let a = 'bread and dream';
  let a = 'dream or bread';
}

(2) 不能在函數內部從新聲明參數:

function demo1(arg) {
  let arg; // 報錯
}
demo1()
function demo2(arg) {
  {
    let arg; // 不報錯
  }
}
demo2()

2. const

2.1 用於聲明常量

const聲明的常量是不容許改變的,只讀屬性,這意味常量聲明時必須同時賦值, 只聲明不賦值,就會報錯,一般常量以大寫字母命名。

const Person;   // 錯誤,必須初始化 
const Person = 'bread and dream';// 正確

const Person2 = 'no'; 
Person2 = 'dream or bread'; //報錯,不能從新賦值

這樣作的兩個好處:一是閱讀代碼的人馬上會意識到不該該修改這個值,二是防止了無心間修改變量值所致使的錯誤。好比咱們使用nodejs的一些模塊的時候,咱們只是使用對應的模塊(如http模塊),可是並不須要修改nodejs的模塊,這個時候就能夠聲明成const,增長了代碼的可讀性和避免錯誤。

2.2 支持塊級做用域

const和let相似,也是支持塊級做用域.

if (true) {
  const MIN = 5;
}

MIN // Uncaught ReferenceError: MIN is not defined

2.3 不支持變量提高,有暫時性死區

const聲明的常量也是不提高,一樣存在暫時性死區,只能在聲明的位置後面使用。

if (true) {
  console.log(MIN); // ReferenceError
  const MIN = 5;
}

2.4 特殊狀況

若是聲明的常量是一個對象,那麼對於對象自己是不容許從新賦值的,可是對於對象的屬性是能夠賦值的。

const obj = {};
obj.a = 'xiao hua';
console.log(obj.a);    //'xiao hua'

實際上const能保證的,並非變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。

對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,所以等同於常量。

但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針。

至於它指向的數據結構是否是可變的,就徹底不能控制了。所以,將一個對象聲明爲常量必須很是當心。

若是要完全將對象凍結(不可修改其屬性),應該使用Object.freeze(obj)方法。同理,數組也是同樣的。

3. import

ES6採用import來代替node等的require來導入模塊。

import {$} from './jquery.js'

$對象就是jquery中export暴露的對象。

若是想爲輸入的變量從新取一個名字,import命令要使用as關鍵字,將輸入的變量重命名。

import { JQ as $ } from './jquery.js';

注意,import命令具備提高效果,會提高到整個模塊的頭部,首先執行。

4. class

ES6引入了類的概念,有了class這個關鍵字。類的實質仍是函數對象。

先定義一個類:

//定義類
class Animal {
  constructor(name, age) {
        this.name = name;
        this.age = age;
  }    
  setSex(_sex) {
        this.sex=_sex;
  }
}

constructor方法,就是構造方法,也就是ES5時代函數對象的主體,而this關鍵字則表明實例對象。

上面的類也能夠改爲ES5的寫法:

function Animal(name, age){
        this.name = name;
        this.age = age;
}

Animal.prototype.setSex = function (_sex) {
        this.sex=_sex;
}

其實,大多數類的特性均可以經過以前的函數對象與原型來推導。

生成類的實例對象的寫法,與ES5經過構造函數生成對象徹底同樣,也是使用new命令。

class Animal {}
let dog = new Animal();

在類的實例上面調用方法,其實就是調用原型上的方法,由於類上的方法其實都是添加在原型上。

Class其實就是一個function,可是有一點不一樣,Class不存在變量提高,也就是說Class聲明定義必須在使用以前。

5.總結

在ES6以前,JavaScript是沒有塊級做用域的,若是在塊內使用var聲明一個變量,它在代碼塊外面仍舊是可見的。ES6規範給開發者帶來了塊級做用域,let和const都添加了塊級做用域,使得JS更嚴謹和規範。

let 與 const 相同點:

塊級做用域
有暫時性死區 
約束了變量提高 
禁止重複聲明變量

let 與 const不一樣點:

const聲明的變量不能從新賦值,也是因爲這個規則,const變量聲明時必須初始化,不能留到之後賦值。

合理的使用ES6新的聲明方式,不論是面試仍是工做中都有實際的應用,尤爲是工做中,你們必定要儘可能的多使用新的聲明方式,不但可讓代碼更規範,更能夠避免沒必要要的bug,浪費調試時間,進而提升工做效率。

相關文章
相關標籤/搜索