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