關(guān)于js閉包的一些常見的問題解析

一、javascript 代碼

    function fun(n,o) {
        console.log(o);
        return {
            fun:function(m){
                return fun(m,n);
            }
        };
    }
    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);

答案為
a: undefined,0,0,0
b: undefined,0,1,2
c: undefined,0,1,1
思路解析:

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

1、fun(0)時,第一個參數(shù)n為0胡控,第二個參數(shù)o未設(shè)置,console.log(o)為undefined双炕,return值為:
{
fun:function(m){
return fun(m,n); //n為0
}
2贾节、a.fun(1)汁汗;m=1衷畦,代入上方return,得出新的return值為fun(1,0)知牌,執(zhí)行得出console.log(0),return值為:
//fun(1,0) return值為:
{
fun:function(m){
return fun(m,n); //n為0
}
3祈争、a.fun(2);m=2角寸,同理代入上方return菩混,得出新的return值為fun(2,0),執(zhí)行得出console.log(0)扁藕,return值為fun(3,0)沮峡;
4、a.fun(3);m=3同理,代入上方return亿柑,得出新的return值為fun(3,0)邢疙,執(zhí)行得出console.log(0)。

var b = fun(0).fun(1).fun(2).fun(3);

1望薄、與前面a一樣,當執(zhí)行到fun(0)時疟游,第二個參數(shù)未設(shè)置,console.log(o)為undefined痕支;
2颁虐、當執(zhí)行到fun(0).fun(1)時,m為1采转,代入return聪廉,得出新的return值為fun(1,0),執(zhí)行fun(1,0)故慈,console.log(0)板熊,return值為fun(1,1);
3、當執(zhí)行到fun(0).fun(1).fun(2)時察绷,m為2干签,代入return,得出新的return值為fun(2,1)拆撼,執(zhí)行fun(2,1)容劳,console.log(1),return值為(2,2)
4闸度、當執(zhí)行到fun(0).fun(1).fun(2).fun(3)時竭贩,m為3,代入return莺禁,得出新的return值為fun(3,2)留量,執(zhí)行fun(3,2),console.log(2);

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

1、當fun(0)時,與前面b一致楼熄,undefined忆绰;
2、當fun(0).fun(1)時可岂,與前面b一致错敢,console.log(0),得出新的return值為fun(1,1)
因此c.fun(2)就是fun(0).fun(1).fun(2)缕粹,與前面b一致稚茅,console.log(1);
因此c.fun(3)就是fun(0).fun(1).fun(3)平斩,m=3峰锁,代入return,得出新的retrun:fun(3,1)双戳,得出結(jié)果console.log(1)

二虹蒋、javascript 代碼

 for (var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, 0);
    }

答案為:5 5 5 5 5
思路解析::
這個定時器里面有個匿名函數(shù)且有閉包,要打印i此時調(diào)用了它外面的循環(huán)的i,當循環(huán)結(jié)束后才打印出i,所以i每次都是打印最后那個循環(huán)結(jié)束的最新值5

三、javascript 代碼

 var a={};
    var b={key:'b'};
    var c={key:'c'};

    a=123;  // toString = [object Object]
    // console.log(a);  //{[object Object]: 123}
    a[c]=456;
    console.log(a);  //456

答案為:456
思路解析:
其實a變量中只有1個屬性 [object Object](因為只有字符串才可以做屬性名)飒货,它們在通過 [] 訪問對象屬性時,方括號中的表達式將會被求值并被通過調(diào)用它的toString方法轉(zhuǎn)換成一個字符串.此時toString = [object Object],即這里的a=123和a[c]=456分別轉(zhuǎn)換成了a['[object Object]'] = 123和a['[object Object]'] = 456,所以再次賦值就會被覆蓋

四魄衅、javascript 代碼

(function(){
        var a = b = 3;
    })();//函數(shù)自調(diào)

    console.log("a :" + typeof a);//a :undefined
    console.log("b : " + typeof b);//b : number

答案為:a :undefined
b :number
思路解析:
因為在閉包中var聲明的是局部變量,所以這里的a是局部變量塘辅,而b沒有用var聲明晃虫,所以在閉包中b自動變成全局變量,那因此打印的時候扣墩,由于a在這個函數(shù)的外面是沒有聲明而無法找到,而b在閉包里面b=3賦值了哲银,所以輸出b的類型是number

五、javascript 代碼

    function Foo() {
        getName = function () {           alert (1);        };
        return this;
    }
    // 靜態(tài)方法   只能通過 Foo.方法名()
    Foo.getName = function () {   alert (2);  };
    Foo.prototype.getName = function () {  alert (3);  };
    var getName = function () {    alert (4);  };
    function getName() {  alert (5);  }

    Foo.getName();   // 2
    getName();  // 4
    Foo().getName(); // 1
    getName();  // 1
    new Foo.getName(); // 2
    new Foo().getName();  // 3
    new new Foo().getName();  // 3

答案為:2 4 1 1 2 3 3
思路解析:
從題目來看呻惕,getName分別以變量荆责,和函數(shù)變量的形式聲明,涉及到變量聲明提前亚脆。因此實際執(zhí)行是:
function Foo() {
getName = function () { alert (1); };
return this;
}
var getName;//只提前變量聲明
function getName() { alert (5);}//覆蓋var的聲明
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};
1做院、因此Foo.getName()調(diào)用時,首先訪問靜態(tài)屬性濒持,所以返回2键耕;
2、getName();變量聲明提前柑营,函數(shù)聲明提前屈雄,函數(shù)覆蓋變量聲明,所以返回4官套;
3酒奶、Foo().getName();執(zhí)行第一個函數(shù)返回的this蓖议,F(xiàn)oo函數(shù)中賦值一個全局變量 getName=function(){alert(1)},當前作用域沒有g(shù)etName讥蟆,因此會向上層尋找window,覆蓋外面的getName的定義纺阔,返回一個1,瘸彤。同時這時也改變了全局變量,this指向了window笛钝,相當于window.getName质况;
4、 getName();由于前面已經(jīng)將全局變量給替換掉了玻靡,所以直接調(diào)用getName()结榄;
5、new Foo.getName()相當于 new(Foo.getName)()囤捻,這里注意運算符優(yōu)先級臼朗,new一個(Foo.getName),即new了一個靜態(tài)方法里的 Foo.getName對象蝎土,就返回了2 视哑。這里運用了運算符優(yōu)先級,其級別表示分別為:
圓括號()>成員訪問>new帶參數(shù)列表>函數(shù)調(diào)用>new不帶參數(shù)列表>遞增遞減>邏輯運算符>一元加法減法>typeof>算數(shù)>位移>比較>in,instance>條件誊涯,賦值挡毅,逗號
6、(new Foo()).getName();是關(guān)于返回值的問題暴构。在構(gòu)造函數(shù)中跪呈,返回值可以沒有返回值,有返回值的時候檢查是不是引用類型取逾,是基本類型等于undefined耗绿,實例里返回實例化對象,是引用類型的時候返回undefined砾隅,實例返回這個引用類型缭乘。這里返回了this是實例化對象,沒有g(shù)etName屬性琉用,通過原型鏈找到構(gòu)造函數(shù)的原型對象為3堕绩;
7、new new Foo().getName();等價于new ((new Foo()).getName)()邑时,所以也是返回3

六奴紧、javascript 代碼

function ClassA(){
    var value = 4;
    this.getValue = function (){
        return value;
    }
    this.setValue = function (value){
        this.value = value;
    }
}

var classa = new ClassA();
document.write(classa.getValue());  // 4 
classa.setValue(1);   // 給對象classa添加了一個屬性 value 他的是 1

document.write(classa.getValue());  // 4  
document.write(classa.value);  // 1  

答案為:441
思路解析:
1、在這里的this.value其實是原型變量晶丘,在classA函數(shù)內(nèi)部定義為classA.prototype.value黍氮,它 與 var value是兩個不同的變量唐含。
2、這里第一個和第二個classa.getValue()其實都是輸出的var value=4這個值沫浆,而第三個classa.value其實輸出的是this.value的值捷枯,因為這個值已經(jīng)被setValue賦值為1了。
3专执、this.value和var value=4這個value是兩個不同的變量淮捆, 而this.value和(classa.value和(classa.prototype.value是同一個變量

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市本股,隨后出現(xiàn)的幾起案子攀痊,更是在濱河造成了極大的恐慌,老刑警劉巖拄显,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苟径,死亡現(xiàn)場離奇詭異,居然都是意外死亡躬审,警方通過查閱死者的電腦和手機棘街,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來承边,“玉大人蹬碧,你說我怎么就攤上這事〕吹螅” “怎么了恩沽?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長翔始。 經(jīng)常有香客問我罗心,道長,這世上最難降的妖魔是什么城瞎? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任渤闷,我火速辦了婚禮,結(jié)果婚禮上脖镀,老公的妹妹穿的比我還像新娘飒箭。我一直安慰自己,他們只是感情好蜒灰,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布弦蹂。 她就那樣靜靜地躺著,像睡著了一般强窖。 火紅的嫁衣襯著肌膚如雪凸椿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天翅溺,我揣著相機與錄音脑漫,去河邊找鬼髓抑。 笑死,一個胖子當著我的面吹牛优幸,可吹牛的內(nèi)容都是我干的吨拍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼网杆,長吁一口氣:“原來是場噩夢啊……” “哼羹饰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起跛璧,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎新啼,沒想到半個月后追城,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡燥撞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年座柱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片物舒。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡色洞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冠胯,到底是詐尸還是另有隱情火诸,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布荠察,位于F島的核電站置蜀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏悉盆。R本人自食惡果不足惜盯荤,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望焕盟。 院中可真熱鬧秋秤,春花似錦、人聲如沸脚翘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽来农。三九已至芥玉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間备图,已是汗流浹背灿巧。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工赶袄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抠藕。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓饿肺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盾似。 傳聞我的和親對象是個殘疾皇子敬辣,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容