變數提升+函式提升+執行上下文
阿新 • • 發佈:2021-07-14
210310
一、變數宣告提升
- 通過var定義(宣告)的變數,在定義語句之前就可以訪問到
- 值:undefined
二、函式宣告提升
- 通過function宣告的函式,在之前就可以直接呼叫
- 值:函式定義(物件)
var a = 3 function fn(){ /*相當於先聲明瞭a var a;a = undefined 先在自身函式中找變數,再去全域性找 */ console.log(a) //undefined var a = 4 } fn() //undefined console.log(b) //undefined //變數提升 fn2() //可呼叫 函式提升 fn3() //變數提升,不可執行 var b = 3 function fn2(){ console.log('fn2') } var fn3 = function(){ console.log('fn3') }
注意:
先執行變數提升,在執行函式提升(函式優先順序更高:函式提升晚,會覆蓋相同變數名的變數提升)
測試一:
function a(){}
var a
console.log(typeof a) //function
測試二:
var c = 1 //=>①var c
function c(c){
console.log(c)
var c = 3 //無關
}
//=>②c = 1 =>c typeof number
c(2) //報錯c is not a function
三、執行上下文
-
程式碼分類(位置)
- 全域性程式碼
- 函式(區域性)程式碼
-
全域性執行上下文
-
在執行全域性程式碼前將window確定為全域性執行上下文
-
對全域性資料進行預處理(收集資料)
- var定義的全域性變數==>(初始化賦值)undefined,新增為window的屬性
- function宣告的全域性函式==>賦值(函式物件),新增為window的方法
- this==>賦值(window)
-
開始執行全域性程式碼
c = 3 //特殊:未執行語句之前,window中不包含此變數,需用var定義 console.log(a1,window.a1) //undefined a2() //a2() console.log(this) //window var a1 = 2 function a2(){ console.log('a2()') } console.log(a1) //2
-
-
函式執行上下文
-
在呼叫函式,準備執行函式體之前,建立對應的函式執行上下文物件(虛擬的,存在於棧中)
-
對區域性資料進行預處理
- 形參變數>賦值(實參)>新增為執行上下文的屬性
- arguments==>賦值(實參列表),新增為執行上下文的屬性
- var定義的區域性變數==>undefined,新增為執行上下文的屬性
- function宣告的函式==>賦值(函式物件),新增為執行上下文的方法
- this==>賦值(呼叫函式的物件)
-
開始執行函式體程式碼
function f1(a1){ console.log(a1) console.log(a2) a3() console.log(this) console.log(arguments) var a2 = 3 function a3(){ console.log('a3()') } } f1(2,3) //2,undefined,a3(),window,2 3
-
210314執行上下文棧
- 在全域性程式碼執行前,js引擎就會建立一個棧來儲存管理所有的執行上下文物件
- 在全域性執行上下文(window)確定後,將其新增到棧中(壓棧)
- 在函式執行上下文建立後,將其新增到棧中(壓棧)
- 在當前函式執行完後,將棧頂的物件移出(出棧)
- 當所有的程式碼執行完畢,棧中只剩下window
//呼叫一次函式產生一次執行上下文棧n+1(window)
//1、進入window全域性執行上下文
var a = 10
var bar = function(x){
var b = 5
//2、進入foo執行上下文
foo(x + b)
}
var foo = function(y){
var c = 5
console.log(a + c + y)
}
//3、進入bar函式執行上下文
bar(10) //30
console.log('global begin:' + i)
var i = 1
foo(1)
function foo(i){
if(i == 4){
return
}
console.log('foo() begin:' + i)
foo(i + 1)//遞迴呼叫:在函式內部呼叫自己
console.log('foo() end:' + i)
}
console.log('global end:' + i)
/*函式依次輸出:
global begin:undefined
foo() begin:1
foo() begin:2
foo() begin:3
foo() end:3
foo() end:2
foo() end:1
global end:1
整個過程中產生了五個執行上下文
*/