理解js中的做用域

執行期上下文(AO):函數在運行時(或預編譯時),會建立一個叫執行期上下文問的一個內部對象Activation Object(全局的叫Global Object)。AO或GO,他定義了一個函數的執行環境(用來作變量/函數的提高等等),函數執行完畢則會銷燬。es6

做用域:每個函數對象都有一個[[scope]]屬性,他內部存儲了執行期上下文的集合,也就是咱們說的做用域。這個集合是一種鏈式結構,叫作做用域鏈bash

做用域鏈的造成過程

  • 當函數被定義時,這個函數的[[scope]]屬性會指向它的上一級函數的[[scope]]屬性的值的引用
  • 當函數被執行時,這個函數的[[scope]]屬性會在他的最上層添加他本身的執行期上下文(AO)。
  • 當函數執行完成後,他本身的執行期上下文(AO)會被銷燬
  • 當查找某個變量或方法時,會從[[scope]]屬性的最上層一直向下尋找。即先找它本身的AO,若未找到,則再向他的上一級函數的尋找

舉個栗子:函數

function a(){
    function b(){
    	var b = 123
    }
    var a = 10
    b()
}
var glob = 100
a()
複製代碼

1.a函數定義時,它的[[scope]]會指向它的上一級即全局的執行期上下文(GO) ui

在這裏插入圖片描述
2.a函數執行時,他的[[scope]]會在他的最上層(最首位)添加本身的執行期上下文(AO),其祖先級依次下移(後移)。
在這裏插入圖片描述
3.此時,b函數被定義,它的scope屬性指向它的上一級,即a的scope的引用。
在這裏插入圖片描述
4.b函數被執行時,會造成本身的AO,並置於其做用域鏈的最頂端(首部),其他依次下移(後移)。
在這裏插入圖片描述
5.此時,當某個函數內使用某個變量時,會在其做用域鏈上(scope chain)依次尋找. 注:一個函數得AO對象上,還包括this、arguments等屬性,此處不一一介紹

做用域的分類

全局做用域:全局做用域指的是在全局起做用的做用域。通常指上面所說的GOthis

局部做用域(函數做用域):局部做用域指的是在局部起做用的做用域。通常函數的做用域都是局部做用域,即上面的AO。es5

塊做用域:通常而言,塊做用域指的是以{}包含的內容快,函數或變量只在它所在的的快內起做用。es5中不存在塊做用域,es6新增了塊做用域。for循環和if語句的{}屬於塊做用域spa

舉個例子 當咱們使用if語句時,在if語句的內部定義了變量3d

var foo = true
if(foo){
    var c = 2
    console.log(c) // 2
}
console.log(c)  // 2
複製代碼

變量c只在if所在的代碼塊中使用,所以將他聲明在if語句內部是很必要的,可是經過var聲明的變量最終都會屬於外部做用域。至關於如下代碼code

var foo = true
var c
if(foo){
    c = 2
    console.log(c) // 2
}
console.log(c)  // 2
複製代碼

因此就須要一些其餘的結構或語法來實現塊級做用域。在es6中新增了let/const,用來聲明變量 let會把變量綁定在它所在的塊中。 const用來聲明常量,也會造成塊級做用域。cdn

var foo = true
if(foo){
    let c = 2
    console.log(c)
}

console.log(c)  // 報錯
複製代碼

因爲let會造成塊級做用域,因此if(){}外接受不到c變量,因此會報錯

相關文章
相關標籤/搜索