摘要:函數和變量相比,會被優先提升。這意味著函數會被提升到更靠前的位置。僅提升聲明,而不提升初始化。
JavaScript 函數高級——執行上下文與執行上下文棧(圖解+典型實例分析) 變量提升與函數提升
變量聲明提升
通過 var 定義(聲明)的變量,在定義語句之前就可以訪問到
值:undefined
/* 面試題 : 輸出 undefined */ var a = 3 function fn() { console.log(a) // undefined 調用fn()后進入函數體內部,通過 var 聲明的變量提升,值為undefined var a = 4 console.log(a) // 4 } fn() console.log("----")
可以用開發工具的代碼調試工具設置斷點,清楚地看到a的值的變化。
函數聲明提升
通過 function 聲明的函數,在該函數聲明之前就可以直接調用
值:函數定義(對象)
console.log(b) // undefined 通過 var 聲明的變量b 變量聲明提升 fn2() // fn2() 通過 function 聲明的函數fn2 函數聲明提升 fn3() // 報錯 通過 var 聲明的函數fn3 變量聲明提升 var b = 3 function fn2() { console.log("fn2()") } var fn3 = function () { console.log("fn3()") }
!!注意 var a = 3, var fn = function(){ }只要是var聲明的,都是變量聲明提升,值都是undefined
??!注意:var fn = function(){ }屬于變量聲明提升,不是函數聲明提升
問題:變量提升和函數提升是如何產生的?
這是因為在JavaScript中執行上下文的工作方式造成的。
函數和變量相比,會被優先提升。這意味著函數會被提升到更靠前的位置。
JavaScript 僅提升聲明,而不提升初始化。
執行上下文個數 = n(調用的函數個數) + 1(全局執行上下文)
// 變量聲明提升,函數聲明提升,全局代碼的函數和方法添加為Window的方法和屬性 console.log(a1, window.a1) // undefined undefined window.a2() // a2() console.log(this) // Window var a1 = 3 function a2() { console.log("a2()") } console.log(a1) // 3代碼分類(位置)
全局代碼
函數代碼
全局執行上下文在執行全局代碼前將window確定為全局執行上下文
對全局數據進行預處理:
var 定義的全局變量==>undefined,添加為window屬性
function 聲明的全局函數==>賦值(fun),添加為window的方法
this==>賦值(window)
開始執行全局代碼
函數執行上下文在調用函數,準備執行函數體之前,創建對應的函數執行上下文對象
對局部數據進行預處理
形參變量==>賦值(實參)==>添加為執行上下文的屬性
arguments==>賦值(實參列表),添加為執行上下文的屬性
var 定義的局部變量==>undefined==>添加為執行上下文的屬性
function聲明的函數==>賦值(fun)==>添加為執行上下文的屬性
this==>賦值(調用函數的對象)
開始執行函數體代碼
執行上下文棧 理解在全局代碼執行前, JS引擎就會創建一個棧來存儲管理所有的執行上下文對象
在全局執行上下文(window)確定后, 將其添加到棧中(壓棧)
在函數執行上下文創建后, 將其添加到棧中(壓棧)
在當前函數執行完后,將棧頂的對象移除(出棧)
當所有的代碼執行完后, 棧中只剩下window
流程分析// 1. 進入全局上下文 var a = 10 var bar = function (x) { var b = 5 // 3. 進入foo執行上下文 foo(x + b) } var foo = function (y) { var c = 5 console.log(a + c + y) } // 2. 進入bar函數執行上下文 bar(10) // 30
用斷點調試工具查看執行上下文調用棧
面試題 題1:遞歸調用的執行上下文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) // ge:1
依次輸出什么?
整個過程中產生了幾個執行上下文?
5個 = 4個函數執行上下文 + 1個全局執行上下文
調試查看:
console.log(foo) // ? foo() {console.log("函數聲明")} console.log(foo()) // 我是一個函數 undefined function foo() { console.log("我是一個函數") } var foo = 3 console.log(foo) // 3 console.log(foo()) // foo is not a function
相當于
function foo(){ console.log("函數聲明") } // 函數聲明先提升 var foo // 變量聲明提升,變量初始化未提升,此時foo的值為undefined,所以不會覆蓋函數聲明 console.log(foo) // 打印出? foo() {console.log("函數聲明")} console.log(foo()) // 我是一個函數 undefined foo = 3 // 此時給foo賦值為3,則會覆蓋前面的 console.log(foo) // 3 console.log(foo()) // foo is not a function,因為此時foo=3題3:考察全局環境下的變量提升
if (!(t in window)) { var t = 1 } console.log(t) // undefined
t in window // true
原因就在于變量t被提升到了全局環境最頂部,通過關鍵字var在全局作用域中聲明的變量將作為全局對象(window)的一個屬性,上面的代碼JavaScript其實是這樣解析的:
var t if (!(t in window)) { var t = 1 } console.log(t) // undefined題4(好題)
var c = 1 function c(c) { console.log(c) var c = 3 } c(2) // 報錯 c is not a function
注意:函數提升為c(),整個函數提升,所以上面的代碼相當于下面這樣,這樣就很清楚了吧!
function c(c) { console.log(c) var c = 3 } var c c = 1 c(2) //所以 c is not a function
函數體內的代碼根本就沒機會執行。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104157.html
摘要:因此,所有在方法中定義的變量都是放在棧內存中的當我們在程序中創建一個對象時,這個對象將被保存到運行時數據區中,以便反復利用因為對象的創建成本通常較大,這個運行時數據區就是堆內存。 上一篇:《javascript高級程序設計》筆記:繼承近幾篇博客都會圍繞著圖中的知識點展開 showImg(https://segmentfault.com/img/bVY0C4?w=1330&h=618);...
摘要:本計劃一共期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃,點擊查看前端進階的破冰之旅本期推薦文章深入之執行上下文棧和深入之變量對象,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第一期,本周的主題是調用堆棧,今天是第二天。 本計劃一共28期,每期...
摘要:首次運行代碼時,會創建一個全局執行上下文并到當前的執行棧中。執行上下文的創建執行上下文分兩個階段創建創建階段執行階段創建階段確定的值,也被稱為。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第一期,本周的主題是調用堆棧,,今天是第一天 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進...
摘要:進階期理解中的執行上下文和執行棧進階期深入之執行上下文棧和變量對象但是今天補充一個知識點某些情況下,調用堆棧中函數調用的數量超出了調用堆棧的實際大小,瀏覽器會拋出一個錯誤終止運行。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第一期,本周的主題是調用堆棧,今天是第3天。 本計劃一共28期,每期重點攻...
摘要:使用上一篇文章的例子來說明下自由變量進階期深入淺出圖解作用域鏈和閉包訪問外部的今天是今天是其中既不是參數,也不是局部變量,所以是自由變量。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第7天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進階計...
閱讀 2191·2021-11-19 09:55
閱讀 2648·2021-11-11 16:55
閱讀 3182·2021-09-28 09:36
閱讀 1951·2021-09-22 16:05
閱讀 3280·2019-08-30 15:53
閱讀 1812·2019-08-30 15:44
閱讀 2902·2019-08-29 13:10
閱讀 1346·2019-08-29 12:30