欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一道JS前端閉包面試題解析

 更新時間:2015年12月25日 15:48:00   作者:kikong  
這篇文章主要針對一道JS前端閉包面試題進行解析,從例題出發(fā)詳細介紹JS前端閉包相關(guān)知識,感興趣的小伙伴們可以參考一下

問題

代碼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);

求出程序輸出

這是一個閉包測試題

轉(zhuǎn)換為等價代碼

return返回的對象的fun屬性對應(yīng)一個新建的函數(shù)對象,這個函數(shù)對象將形成一個閉包作用域,使其能夠訪問外層函數(shù)的變量n及外層函數(shù)fun,為了不將fun函數(shù)和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

那么就有同學(xué)問了,為什么可以這樣改呢,你怎么能確定[1]處的fun不是[2]代碼所在處的fun呢,要知道此處的fun屬性可是指向一個函數(shù)對象哦~
這里就要說到JS的詞法作用域,JS變量作用域存在于函數(shù)體中即函數(shù)體,并且變量的作用域是在函數(shù)定義聲明的時候就是確定的,而非在函數(shù)運行時。
如下代碼

var name="global";
function foo(){
  console.log(name);
}

function fooOuter1(){
  var name="local";
  foo();
}
fooOuter1();//輸出global 而不是local,并且和閉包沒有任何關(guān)系

function fooOuter2(){
  var name="local";
  function foo(){
    console.log(name);
  }
  foo();
}
fooOuter2();//輸出local 而不是global,在函數(shù)聲明是name變量作用域就在其外層函數(shù)中,嗯嗯就是閉包~

好了我們回到題目,在函數(shù)聲明定義階段,[2]處的匿名函數(shù)進行定義聲明,發(fā)現(xiàn)在[1]處需要引用一個名為fun的函數(shù)對象,那么首先在當前函數(shù)體內(nèi)尋找,發(fā)現(xiàn)沒有,那么就到其外層函數(shù)-這個匿名函數(shù)的包裹函數(shù)中去查找,發(fā)現(xiàn)也沒有,到外層函數(shù)中去,發(fā)現(xiàn)外面沒有函數(shù)包裹了,那就到全局環(huán)境下去找,額偶終于找到了......就把fun函數(shù)指定為全局環(huán)境下的fun函數(shù)對象并加入到匿名函數(shù)的閉包中去。至此我們就知道代碼B為什么和代碼A是等價的了~~~

創(chuàng)建閉包作用域

JS在詞法分析結(jié)束后,確定了1個閉包,就是返回的對象fun屬性對應(yīng)的匿名函數(shù)的閉包-訪問全局環(huán)境下的_func_及其外層函數(shù)的函數(shù)內(nèi)部變量n;
在每次_func_執(zhí)行的時候,都會將閉包中變量的作用域信息傳遞到函數(shù)執(zhí)行環(huán)境中,供函數(shù)執(zhí)行時獲取變量值時使用

執(zhí)行輸出

var a=_fun_(0);//undefined
a.fun(1);//0
a.fun(2);//0
a.fun(3);//0

_fun_函數(shù)執(zhí)行,因為第2個參數(shù)未定義,輸出undefined。然后返回一個對象,帶有fun屬性,指向一個函數(shù)對象-帶有閉包,能夠訪問到_fun_和變量n_
a.fun(1)執(zhí)行返回的對象的fun方法,傳入m的值1,調(diào)用返回_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]被調(diào)用時,b1對象中有一個閉包,引用了_fun_函數(shù)及外層函數(shù)變量n=1,所以匿名函數(shù)執(zhí)行的函數(shù)調(diào)用為_fun_(2,1),輸出結(jié)果為1,并返回一個新的對象。
當[4]執(zhí)行時,b2對象也有一個閉包,引用了_fun_函數(shù)及外層函數(shù)變量n=2,執(zhí)行_fun_(3,2),輸出結(jié)果為2

var c=fun(0).fun(1);//undefined,0,
c.fun(2);//1
c.fun(3); //1

能看懂前面的代碼執(zhí)行解釋,理解上面的代碼執(zhí)行輸出就不會有問題了,希望大家喜歡。

相關(guān)文章

  • 你未必知道的JavaScript和CSS交互的5種方法

    你未必知道的JavaScript和CSS交互的5種方法

    網(wǎng)頁中都有.js文件和.css文件,但這并不意味著CSS和js是獨立不能交互的,下面與大家分享js與css交互的5種方法
    2014-04-04
  • JavaScript Generator函數(shù)使用分析

    JavaScript Generator函數(shù)使用分析

    生成器Generator是JavaScript ES6引入的特性,它讓我們可以分段執(zhí)行一個函數(shù)。但是在談?wù)撋善鳎℅enerator)之前,我們要先了解迭代器Iterator
    2022-10-10
  • 利用JS實現(xiàn)二叉樹遍歷算法實例代碼

    利用JS實現(xiàn)二叉樹遍歷算法實例代碼

    眾所周知javascript語言中只提供了幾種基本類型的數(shù)據(jù)類型,而二叉樹是一種數(shù)據(jù)結(jié)構(gòu),在一些查詢等操作中能提供較好的性能,這篇文章主要給大家介紹了關(guān)于利用JS實現(xiàn)二叉樹遍歷算法的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • 淺談js中test()函數(shù)在正則中的使用

    淺談js中test()函數(shù)在正則中的使用

    下面小編就為大家?guī)硪黄獪\談js中test()函數(shù)在正則中的使用。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • JavaScript this指向相關(guān)原理及實例解析

    JavaScript this指向相關(guān)原理及實例解析

    這篇文章主要介紹了JavaScript this指向相關(guān)原理及實例解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • 設(shè)為首頁與加入收藏的JS代碼(多瀏覽器支持)

    設(shè)為首頁與加入收藏的JS代碼(多瀏覽器支持)

    由于現(xiàn)在很多瀏覽器版本,那么多瀏覽器兼容的設(shè)為首頁與加入收藏功能代碼,就比較好用,這里簡單的整理下,方便需要的朋友
    2012-12-12
  • 最新評論