這裏主要記錄在平常中對知識的學習,經過結合筆記與自身理解的方式嘗試寫下總結
文章對細節可能不會一一介紹解釋,內容僅做參考
複製代碼
上次寫了做用域相關的知識總結,這篇文章是它的進一步提高。若是對做用域還不是很瞭解,能夠先看一下:JavaScript做用域相關的總結javascript
我翻了挺多文章,感受他們對上下文這個詞的解釋都有些抽象,不如干脆就放過他的字面意義,而是記住他是如何產生的,以及做用java
當JavaScript執行一段可執行代碼時,就會先創建對應的執行上下文app
執行上下文的代碼會分紅兩個階段進行:函數
在生成的每一個執行上下文中,都會有3個重要的屬性:post
變量對象是與執行上下文相關的數據域,存儲了在上下文中定義的變量和函數聲明學習
在進入執行上下文時(未代碼執行),變量對象會進行初始化,包括:ui
舉個栗子:this
function a(n, m) {
var b = 1
function c() {
console.log('c')
}
var d = function() {
console.log('d')
}
b = 2
}
a(10, 20)
複製代碼
在進入執行上下文後,此時的變量對象是這樣的:spa
變量對象 = {
arguments: {
0: 10,
1: 20,
length: 2
},
n: 10,
m: 20,
b: undefined,
c: function, d: undefined } 複製代碼
等到了代碼執行時,代碼會順序執行,從而更改變量對象的值。當代碼執行到最尾時,變量對象是這樣的:code
變量對象 = {
arguments: {
0: 10,
1: 20,
length: 2
},
n: 10,
m: 20,
b: 1 -> 2,
c: function, d: functionExpression } 複製代碼
在函數中,當查找變量的時候,會先從當前上下文的變量對象中查找,若是沒有找到,就會從父級(詞法層面)執行上下文的變量對象查找,一直找到全局上下文的變量對象。這樣由多個執行上下文的變量對象構成的鏈表就叫作做用域鏈
在做用域總結中已經提過,對於一個變量的查找方向是在做用域定義的時候就已經約定好的
JavaScript有一套不一樣於其餘語言的對this的處理機制。在五種不一樣的狀況下,this指向的各不相同
常見誤解
Foo.method = function() {
function test() {
console.log(this)
}
test() // window
}
複製代碼
這裏會被認爲test函數中的this會指向Foo對象,實際上不是這樣子的,而是會指向全局對象。若是想拿到Foo的內部this,能夠這樣寫
Foo.method = function() {
let that = this
function test() {
console.log(that)
}
test() // Foo
複製代碼
let a = {
b: function() {
console.log(this.c)
},
c: 1
}
let mb = a.b
mb() // undefined (指向window)
複製代碼
另外一個看起來奇怪的地方是函數別名,也就是將一個方法賦值給一個變量。上例中b 就像一個普通的函數被調用。所以,函數內的 this 不被指向到 a 對象,而是全局對象
以上三個屬性構成了執行上下文的做用,使得在代碼執行時可以使用相關的特性