摘要:當執行時,對象也有一個閉包,引用了函數及外層函數變量,執行輸出結果為能看懂前面的代碼執行解釋,理解上面的代碼執行輸出就不會有問題了
問題
代碼A
function fun(n,o){ console.log(o); return { fun:function(m){//[2] return fun(m,n);//[1] } } } var a=fun(0); a.fun(1); a.fun(2); a.fun(3); var b=fun(0).fun(1).fun(2).fun(3); var c=fun(0).fun(1); c.fun(2); c.fun(3);
求出程序輸出
這是一個閉包測試題
轉換為等價代碼return返回的對象的fun屬性對應一個新建的函數對象,這個函數對象將形成一個閉包作用域,使其能夠訪問外層函數的變量n及外層函數fun,為了不將fun函數和fun屬性搞混,我們將上述代碼修改如下:
代碼B
function _fun_(n,o){ console.log(o); return { fun:function(m){ return _fun_(m,n); } } } var a=_fun_(0);//undefined a.fun(1);//0 a.fun(2);//0 a.fun(3);//0 var b=_fun_(0).fun(1).fun(2).fun(3); //undefined,0,1,2 var c=_fun_(0).fun(1);//undefined,0, c.fun(2);//1 c.fun(3); //1
那么就有同學問了,為什么可以這樣改呢,你怎么能確定[1]處的fun不是[2]代碼所在處的fun呢,要知道此處的fun屬性可是指向一個函數對象哦~
這里就要說到JS的詞法作用域,JS變量作用域存在于函數體中即函數體,并且變量的作用域是在函數定義聲明的時候就是確定的,而非在函數運行時。
如下代碼
var name="global"; function foo(){ console.log(name); } function fooOuter1(){ var name="local"; foo(); } fooOuter1();//輸出global 而不是local,并且和閉包沒有任何關系 function fooOuter2(){ var name="local"; function foo(){ console.log(name); } foo(); } fooOuter2();//輸出local 而不是global,在函數聲明是name變量作用域就在其外層函數中,嗯嗯就是閉包~
好了我們回到題目,在函數聲明定義階段,[2]處的匿名函數進行定義聲明,發現在[1]處需要引用一個名為fun的函數對象,那么首先在當前函數體內尋找,發現沒有,那么就到其外層函數-這個匿名函數的包裹函數中去查找,發現也沒有,到外層函數中去,發現外面沒有函數包裹了,那就到全局環境下去找,額偶終于找到了......就把fun函數指定為全局環境下的fun函數對象并加入到匿名函數的閉包中去。至此我們就知道代碼B為什么和代碼A是等價的了~~~
創建閉包作用域JS在詞法分析結束后,確定了1個閉包,就是返回的對象fun屬性對應的匿名函數的閉包-訪問全局環境下的_func_及其外層函數的函數內部變量n;
在每次_func_執行的時候,都會將閉包中變量的作用域信息傳遞到函數執行環境中,供函數執行時獲取變量值時使用
var a=_fun_(0);//undefined a.fun(1);//0 a.fun(2);//0 a.fun(3);//0
_fun_函數執行,因為第2個參數未定義,輸出undefined。然后返回一個對象,帶有fun屬性,指向一個函數對象-帶有閉包,能夠訪問到_fun_和變量n_
a.fun(1)執行返回的對象的fun方法,傳入m的值1,調用返回_fun_(1,0)
所以輸出為0,a.fun(2),a.fun(3)和a.fun(1)
var b=_fun_(0).fun(1).fun(2).fun(3);
等價代碼
var b=_fun_(0); var b1=b.fun(1); var b2=b1.fun(2);//[3] var b3=b2.fun(3);//[4]
前2句和上面的輸出相同undefined,0,當[3]被調用時,b1對象中有一個閉包,引用了_fun_函數及外層函數變量n=1,所以匿名函數執行的函數調用為_fun_(2,1),輸出結果為1,并返回一個新的對象。
當[4]執行時,b2對象也有一個閉包,引用了_fun_函數及外層函數變量n=2,執行_fun_(3,2),輸出結果為2
var c=fun(0).fun(1);//undefined,0, c.fun(2);//1 c.fun(3); //1
能看懂前面的代碼執行解釋,理解上面的代碼執行輸出就不會有問題了
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78361.html
摘要:然后最外層這個函數會返回一個新對象,對象里面有一個屬性,名為,而這個屬性的值是一個匿名函數,它會返回。 最近看到一條有意思的閉包面試題,但是看到原文的解析,我自己覺得有點迷糊,所以自己重新做一下這條題目。 閉包面試題原題 function fun(n, o) { // ① console.log(o); return { // ② fun: function(m) ...
摘要:函數式編程前端掘金引言面向對象編程一直以來都是中的主導范式。函數式編程是一種強調減少對程序外部狀態產生改變的方式。 JavaScript 函數式編程 - 前端 - 掘金引言 面向對象編程一直以來都是JavaScript中的主導范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數式編程越來越多得受到開發者的青睞。函數式編程是一種強調減少對程序外部狀態產生改變的方式。因此,...
摘要:獲取的對象范圍方法獲取的是最終應用在元素上的所有屬性對象即使沒有代碼,也會把默認的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對于一個光禿禿的元素,方法返回對象中屬性值如果有就是據我測試不同環境結果可能有差異而就是。 花了很長時間整理的前端面試資源,喜歡請大家不要吝嗇star~ 別只收藏,點個贊,點個star再走哈~ 持續更新中……,可以關注下github 項目地址 https:...
摘要:最近遇到的前端面試題更新版前端掘金個人博客已上線,歡迎前去訪問評論無媛無故的個人博客以下內容非本人原創,是整理后覺得更容易理解的版本,歡迎補充。 一道面試題引發的對 javascript 類型轉換的思考 - 前端 - 掘金 最近群里有人發了下面這題:實現一個函數,運算結果可以滿足如下預期結果: ... 收集 JavaScript 各種疑難雜癥的問題集錦 - 前端 - 掘金 從原博客遷移...
摘要:最近遇到的前端面試題更新版前端掘金個人博客已上線,歡迎前去訪問評論無媛無故的個人博客以下內容非本人原創,是整理后覺得更容易理解的版本,歡迎補充。 一道面試題引發的對 javascript 類型轉換的思考 - 前端 - 掘金 最近群里有人發了下面這題:實現一個函數,運算結果可以滿足如下預期結果: ... 收集 JavaScript 各種疑難雜癥的問題集錦 - 前端 - 掘金 從原博客遷移...
閱讀 1670·2021-10-13 09:39
閱讀 2099·2021-09-07 10:20
閱讀 2678·2019-08-30 15:56
閱讀 2945·2019-08-30 15:56
閱讀 932·2019-08-30 15:55
閱讀 625·2019-08-30 15:46
閱讀 3494·2019-08-30 15:44
閱讀 2552·2019-08-30 11:15