深入理解ES6(一)

塊級作用域綁定

var聲明及變量提升機制

在ES6之前,在函數作用域中或者全局作用域中通過var關鍵字來聲明變量,無論是在代碼的哪個位置,這條聲明語句都會提到最頂部來執行,這就是變量聲明提升。

注意:只是聲明提升,初始化並沒有提升。

function getStudent(name){
  if(name){
    var age=25;
  }else{
    console.log("name不存在");      
  }
  console.log(age); //undefined
}

如果按照預想的代碼的執行順序,當name有值時纔會創建變量age,可是執行代碼發現,即使不傳入name,判斷語句外的輸出語句並沒有報錯,而是輸出undefined

這就是變量聲明提升。

塊級聲明

ES6前是沒有塊級作用域的,比如{}外可以訪問內部的變量。

let聲明

  • 聲明變量
  • 作用域限制在當前代碼塊
  • 聲明不會提升
  • 禁止重聲明(同一作用域不行,可以覆蓋外部同名變量)
function getStudent(name){
  if(name){
    let age=25;
    console.log(age); //25
  }else{
    console.log("name不存在");      
  }
  console.log(age); //age is not defined
}

和上文一樣的代碼,只是將age的命名關鍵字從var改成了let,在執行getStudent()getStudent("axuebin")時都會報錯。

原因:

  • 在if語句內部執行之後,age變量將立即被銷燬
  • 如果name爲空,則永遠都不會創建age變量

const聲明

  • 聲明常量
  • 必須初始化
  • 不可更改
  • 作用域限制在當前代碼塊
  • 聲明不會提升
  • 禁止重聲明(同一作用域不行,可以覆蓋外部同名變量)

如果用const來聲明對象,則對象中的值可以修改。

臨時死區(Temporal Dead Zone)

JavaScript引擎在掃面代碼發現聲明變量時,遇到var則提升到作用域頂部,遇到letconst則放到TDZ中。當執行了變量聲明語句後,TDZ中的變量才能正常訪問。

循環中的塊作用域綁定

我們經常使用for循環:

for(var i=0;i<10;i++){
  console.log(i); //0,1,2,3,4,5,6,7,8,9
}
console.log(i) //10

發現了什麼?

在for循環執行後,我們仍然可以訪問到變量i

 把var換成let就解決了

for(let i=0;i<10;i++){
  console.log(i); //0,1,2,3,4,5,6,7,8,9
}
console.log(i) //i is not defined

講閉包時setTimeout循環各一秒輸出i的jin例子

for(var i=0;i<10;i++){
  setTimeout(function(){
    console.log(i); //10,10,10.....
  },1000)
}

很顯然,上面的代碼輸出了10次的10,setTimeout在執行了循環之後才執行,此時i已經是10了~

之前,我們這樣做 ~

for(var i=0;i<10;i++){
  setTimeout((function(i){
    console.log(i); //0,1,2,3,4,5,6,7,8,9
  })(i),1000)
}

現在,我們這樣做 ~ 來看看把var改成let會怎樣~

for(let i=0;i<10;i++){
  setTimeout(function(){
    console.log(i); //0,1,2,3,4,5,6,7,8,9
  },1000)
}

全局塊作用域綁定

  1. 全局對象是最頂層的對象,在瀏覽器環境指的是window對象,在 Node.js 指的是global對象。 ES5 之中,全局對象的屬性與全局變量是等價的。
window.a = 1;
a // 1
a = 2;
window.a // 2
  • 未聲明的全局變量,自動成爲全局對象window的屬性,這被認爲是 JavaScript 語言最大的設計敗筆之一。
  • ES6 爲了改變這一點,一方面規定,爲了保持兼容性,var命令和function命令聲明的全局變量,依舊是全局對象的屬性;
  • 另一方面規定,let命令、const命令、class命令聲明的全局變量,不屬於全局對象的屬性。也就是說,從 ES6 開始,全局變量將逐步與全局對象的屬性脫鉤。
var a = 1;
//  如果在 Node 的 REPL 環境,可以寫成 global.a
//  或者採用通用方法,寫成 this.a
window.a // 1
let b = 1;
window.b // undefined

  • 上面代碼中,全局變量a由var命令聲明,所以它是全局對象的屬性;全局變量b由let命令聲明,所以它不是全局對象的屬性,返回undefined



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章