摘要:是一個解釋型語言上明確的說,是一個輕量級的解釋型的面向?qū)ο蟮膶⒑瘮?shù)視為一級公民的語言。全局代碼在執(zhí)行的時候,先是變量提升,在全局作用域內(nèi)添加屬性,然后是函數(shù)以函數(shù)聲明創(chuàng)建的函數(shù)提升,再是代碼執(zhí)行。那么,很顯然,閉包其實就是一個函數(shù)。
JavaScript是一個解釋型語言
MDN上明確的說,JavaScript是一個輕量級的、解釋型的、面向?qū)ο蟮?、將函?shù)視為一級公民的語言。
那么,既然js是一個解釋型語言,那它就是在運行時把代碼轉(zhuǎn)換成機器可以識別的語言。哪它又為什么會存在變量提升呢?
下面這篇文章給出了解釋,在此也特別感謝作者的分享!
https://mp.weixin.qq.com/s/ne...
function fn(c){ console.log(c); //true var c = false; console.log(a); //function a(){} var a = 1; console.log(a); //1 function a(){ }; console.log(a); //1 b(); //函數(shù)聲明 var b = function(){ console.log("函數(shù)表達式"); } function b(){ console.log( "函數(shù)聲明" ) } b(); //函數(shù)表達式 var d = 4; } fn(true);
上面這個fn方法很簡單,相信很多人都能過做出來,但肯定也很多人不理解結(jié)果為什么是這樣!
那么這個過程是怎樣執(zhí)行的呢:
首先,js在執(zhí)行前會產(chǎn)生一個GO(Global Object),也就是我們常說的全局作用域。當一個方法被調(diào)用的時候會形成一個局部作用域AO(Activation Object)。
全局代碼在執(zhí)行的時候,先是變量提升,在全局作用域內(nèi)添加屬性,然后是函數(shù)(以函數(shù)聲明創(chuàng)建的函數(shù))提升,再是代碼執(zhí)行。
函數(shù)在被調(diào)用的時候,以上面的fn這個方法為例,進入函數(shù)上下文,但是在執(zhí)行代碼之前,經(jīng)歷的階段:
第一階段:首先創(chuàng)建一個AO,并包含下列屬性:
AO : { arguments:, //函數(shù)內(nèi)部參數(shù)的類數(shù)組對象 c: true, //傳入的參數(shù),如果沒有傳遞實參,那么值就是undefined }
第二階段:函數(shù)內(nèi)部的函數(shù)(以函數(shù)聲明創(chuàng)建的函數(shù))提升
AO : { arguments:, c: true, a: function a(){}, b: function b(){ console.log( "函數(shù)聲明" ) } }
第三階段:函數(shù)內(nèi)部的變量提升
AO : { arguments:, c: true, a: function a(){}, b: function b(){ console.log( "函數(shù)聲明" ) }, d: undefined }
函數(shù)內(nèi)部又定義了變量 var c和var a,當變量提升時,發(fā)現(xiàn)AO中已經(jīng)存在a和c屬性,如果變量名稱跟已經(jīng)聲明的形參或函數(shù)相同,則變量聲明不會干擾已經(jīng)存在的這類屬性。如果不相同切不存在,那就會放到AO中,值為undefined。
當上面的這些準備工作做完之后,才會開始執(zhí)行函數(shù)內(nèi)部的代碼,這樣就很好明白,函數(shù)內(nèi)部的變量,在什么階段分別代表什么樣的值!
閉包解析在JavaScript高級程序3中,對閉包的描述是這樣的,閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。那么,很顯然,閉包其實就是一個函數(shù)。
那么我們怎樣通過GO、AO理解閉包呢:
function foo(){ var a = 1; function fnSon(){ a++; console.log(a); } return fnSon; } var fnTest = foo(); fnTest(); //2 fnTest(); //3
當foo這個方法被調(diào)用的時候,創(chuàng)建一個AO,當函數(shù)執(zhí)行完之后AO里面包含了變量a、函數(shù)fnSon
AO:{ a:1, fnSon: function(){} }
此時的fnSon被賦值給了fnTest,那么foo方法的AO在執(zhí)行完之后就沒辦法被銷毀,當fnTest被調(diào)用的時候,代碼執(zhí)行完之后,foo的AO對象中的a變成了2,再次調(diào)用fnTest的時候就變成3。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/106270.html
摘要:所以變量聲明提升和函數(shù)聲明提升會出現(xiàn)一個先后順序預(yù)編譯過程結(jié)束。 先科普: 1.javaScript是解釋型語言,就是編譯一行,執(zhí)行一行.....2.javaScript沒有塊級及作用域......3.javaScript具有變量和函數(shù)聲明提升功能.....4.AO對象和GO對象....5.預(yù)編譯就是解決代碼執(zhí)行順序問題,與java語言類似(jvm).... 例如: (function...
摘要:大家都知道是解釋型語言,既然是解釋型語言,就是編譯一行,執(zhí)行一行,那又何來預(yù)編譯一說呢腳本執(zhí)行引擎都做了什么呢今天我們就來看看吧。全局域就是一切聲明的全局變量,全是的屬性等同于函數(shù)預(yù)編譯發(fā)生在函數(shù)執(zhí)行前一刻。 大家都知道JavaScript是解釋型語言,既然是解釋型語言,就是編譯一行,執(zhí)行一行,那又何來預(yù)編譯一說呢?腳本執(zhí)行js引擎都做了什么呢?今天我們就來看看吧。 1-JavaScr...
摘要:詞法作用域是一種靜態(tài)作用域這個例子的結(jié)果按靜態(tài)作用域來分析執(zhí)行函數(shù),先從函數(shù)內(nèi)部查找是否有局部變量,如果沒有,就根據(jù)書寫的位置,查找上面一層的代碼,也就是等于,所以結(jié)果會打印。靜態(tài)作用域,決定的是作用域鏈的順序。 博客原文地址:https://finget.github.io/2018/03/01/javascriptPrecompile/看不明白的地方歡迎提問,有理解的不對的地方希望...
摘要:正式由于作用域鏈的這種關(guān)系,我們就不難理解,為什么和不能通過作用域鏈向上搜索,因為對和的搜索在當前執(zhí)行函數(shù)的活動對象就停止了。 對于Javascript程序員來說,閉包總會讓你覺得既熟悉又陌生,然而它對于開發(fā)人員來說卻非常重要,javascript里的許多設(shè)計模式中都用到了閉包,此處以函數(shù)作用域為例。 //示例代碼 var a=1; function foo(){ ...
摘要:一概念是一個單線程解釋型的編程語言。預(yù)編譯大致可分為步創(chuàng)建對象找形參和變量聲明,將形參和變量名作為屬性名,值為將實參值和形參統(tǒng)一在函數(shù)體里面找函數(shù)聲明,值賦予函數(shù)體。 一、JavaScript概念 JavaScript ( JS ) 是一個單線程、解釋型的編程語言。 二、JavaScript語言特點 2.1 單線程 JavaScript語言的一大特點就是單線程,也就是說,同一個時間只能...
閱讀 593·2023-04-26 01:42
閱讀 3230·2021-11-22 11:56
閱讀 2407·2021-10-08 10:04
閱讀 855·2021-09-24 10:37
閱讀 3134·2019-08-30 15:52
閱讀 1755·2019-08-29 13:44
閱讀 478·2019-08-28 17:51
閱讀 2150·2019-08-26 18:26