js的作用域鏈是由當前執行環境下的變量對象以及上層的執行環境下的變量對象組成,它保證了當前執行環境對符合訪問它的權限的函數以及變量的訪問順序
以上為例子的話,他們的執行上下文相繼被創建,而他們的變量對象可以這么來表示;
VO(全局){
arguments:.....
function:test()
var :....
}
VO(test){
arguments:....
function:add()
var:a
}
VO(add){
arguments:...
function:...
var:a
}
而add的作用域鏈,則同時包含了這三個變量對象。所以add的執行上下文中的作用域鏈可以這么表示:
add{
VO: ?//變量對象
scopeChain: [VO(add),VO(test),VO(global)], // 作用域鏈
this ? //this指向
}
從他們的關系可以用一個數組來表示
而數組的末端就是全局變量對象
所以作用域鏈可以用一個單方向的通道來表示,以它自己為最前端為起點,最末端為重點,
所以作用域鏈是由一系列變量對象組成的一個單方面的一個通道,這樣我們就可以在這個單方面的通道里面訪問上一層的函數和變量。
閉包的意思
當函數可以記住并且訪問當前作用域(全局作用域除外),即使這個函數是在當前作用域之外執行。
假設一個例子,一個函數???在函數???里面定義并且訪問了函數???里面的變量,那么B九四閉包。
通過閉包,我們可以在其他執行上下文當中,訪問到函數的內部變量。如下例子
this
this的查找
this的查找是很多人迷茫的一點,也似乎有很多人抱有this不穩定這樣的看法,實在令人無語。this的查找可以說是3種對象查找中最為簡單的,因為其實this對象的確定根本沒有一個“查找”的過程。
首先,this對象只會在一個函數中需要確定,如果是在全局域下,this永遠為Global對象,在瀏覽器中通常就是window對象。而在javascript中,函數的調用一共有4種方式:
Function Invocation Pattern
諸如`foo()`的調用形式被稱為Function Invocation Pattern,是函數最直接的使用形式,注意這里的foo是作為單獨的變量出現,而不是屬性。
在這種模式下,foo函數體中的this永遠為Global對象,在瀏覽器中就是window對象。
Method Invocation Pattern
諸如`foo.bar()`的調用形式被稱為Method Invocation Pattern,注意其特點是被調用的函數作為一個對象的屬性出現,必然會有“.”或者“[]”這樣的關鍵符號。
在這種模式下,bar函數體中的this永遠為“.”或“[”前的那個對象,如上例中就一定是foo對象。
Constructor Pattern
`new foo()`這種形式的調用被稱為Constructor Pattern,其關鍵字`new`就很能說明問題,非常容易識別。
在這種模式下,foo函數內部的this永遠是new foo()返回的對象。
Apply Pattern
`foo.call(thisObject)`和`foo.apply(thisObject)`的形式被稱為Apply Pattern,使用了內置的`call`和`apply`函數。
在這種模式下,`call`和`apply`的第一個參數就是foo函數體內的this,如果thisObject是`null`或`undefined`,那么會變成Global對象。
應用以上4種方式,確定一個函數是使用什么樣的Pattern進行調用的,就能很容易確定this是什么。
另外,this是永遠不會延作用域鏈或原原型鏈出現一個“查找”的過程的,只會在函數調用時就完全確認。?