天天看點

03------JS函數進階之執行上下文與執行上下文棧

執行上下文與執行上下文棧

1.變量提升與函數提升

變量聲明提升

  • 通過var定義(聲明)的變量,在定義語句之前就可以通路到
  • 值:undefined

函數聲明提升

  • 通過function聲明的函數,在之前就可以直接調用
  • 值:函數定義(對象)
var a = 3
function fn() {
	console.log(a) // undefined
	var a = 4
}
fn()
console.log(b) // unfefined 變量提升
fn2() //可調用 函數提升
var b = 3
function fn2() {
	console.log('fn2()')
}
           

問題:變量提升和函數提升是如何産生的?

變量提升和函數提升引申出執行上下文和執行上下文棧

2.執行上下文

全局執行上下文

  • 在執行全局代碼前将window确定為全局執行上下文
  • 對全局資料進行預處理
    • var定義的全部變量---->undefined,添加為window的屬性
    • function聲明的全局函數---->指派(fun),添加為window的方法
    • this---->指派(window)
  • 開始執行全局代碼

函數執行上下文(虛拟的,存在于棧中)

  • 在調用函數,準備執行函數體之前,建立對應的函數執行上下文對象
  • 對局部資料進行預處理
    • 形參變量---->指派(實參)---->添加為執行上下文的屬性
    • arguments---->指派(實參清單),添加為執行上下文的屬性
    • var定義的局部變量---->undefined,添加執行上下文的屬性
    • function聲明的函數---->指派(fun),添加執行上下文的屬性
    • this---->指派(調用函數的對象)
  • 開始執行函數體代碼
// 函數執行上下文
function fn(a1) {
	console.log(a1) // 2
	console.log(a2) // undefined
	a3() // a3()
	console.log(this) // window
	console.log(arguments) // 僞數組(2, 3)
	
	var a2 = 3
	function a3() {
		console.log('a3()')
	}
}
fn(2, 3)
           

3.執行上下文棧

  • 在全局代碼執行前,JS引擎就會建立一個棧來存儲管理所有的執行上下文對象
  • 在全局執行上下文(window)确定後,将其添加到棧中(壓棧)
  • 在函數執行上下文建立後,将其添加到棧中(壓棧)
  • 在目前函數執行完後,将棧頂的對象移除(出棧)
  • 當所有的代碼執行完後,棧中隻剩下window
<script type="text/javascript">
//1.進入全局執行上下文
var a = 10
var bar = function (x) {
	var b = 5
	foo(x + b) // 3.進入foo執行上下文
}
var foo = function (y) {
	var c = 5
	console.log(a + c + y)
}
bar(10) // 2.進入bar函數執行上下文
</script>
           

圖解

03------JS函數進階之執行上下文與執行上下文棧

注意:棧底的執行上下文一定是window,總在底部

面試題:

1).

<script type="text/javascript">
console.log('gb:' + i)
var i = 1
foo(1)
function foo(i) {
	if(i == 4) {
		return
	}
	console.log('fb:' + i)
	foo(i + 1) // 遞歸函數
	console.log('fe: ' + i)
}
console.log('ge:' + i)
// 1.依次輸出什麼?
// gb:undefined
// fb:1
// fb:2
// fb:3
// fe:3
// fe:2
// fe:1
// fe:1
// 2.整個過程中産生了幾個執行上下文? 5個
</script>
           

2).

// 先執行變量提升,再執行函數提升
function a() {}
var a;
console.log(typeof a) // 'function'

if(!(b in window)) {
	var b = 1
}
console.log(b) // undefined
           

3).

var c = 1
function c(c) {
	console.log(c)
}
c(2) //報錯 c不是function 變量提升
           

繼續閱讀