閉包、定時(shí)器

問(wèn)答

1.什么是閉包础拨?有什么作用氮块?

  • 閉包
    閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。在JavaScript中诡宗,只有函數(shù)內(nèi)部的子函數(shù)才能夠讀取內(nèi)部變量滔蝉,因此可以把閉包簡(jiǎn)單理解成“定義在一個(gè)函數(shù)內(nèi)部的函數(shù)∷郑”
    比如在函數(shù)內(nèi)部讀取它的內(nèi)部變量:
function f1(){
       var n = 999;
       function f2(){
              console.log(n);
       }
       return f2;
}
var result = f1();
resulet(); //999

上段代碼中蝠引,函數(shù)f2就是閉包。

  • 作用
    1.可以讀取函數(shù)內(nèi)部的變量。
    2.讓這些變量始終保存在內(nèi)存中螃概。
    舉例來(lái)看閉包的作用:
function f1(){
       var n = 999;
       nAdd = function(){n+=1}
       function f2(){
       console.log(n);
       }
        return f2;
}
var result = f1();
result();//999
nAdd();
result();//1000

這段代碼中矫夯,函數(shù)f2就是閉包,它一共運(yùn)行了2次吊洼,第一次是999训貌,第二次是1000,這說(shuō)明了函數(shù)f1的局部變量n一直保存在內(nèi)存中冒窍,并沒(méi)有在f1調(diào)用后清除递沪。

原因是f2被賦給了一個(gè)全局變量result,導(dǎo)致f2一直存在內(nèi)存中综液,而f2的存在依賴于f1款慨,所以f1也始終在內(nèi)存中。

2. setTimeout 0有什么作用

setTimeout函數(shù)用來(lái)指定某個(gè)函數(shù)或某段代碼在多少毫秒之后執(zhí)行意乓,它接受兩個(gè)參數(shù)樱调,要執(zhí)行的代碼和以毫秒表示的時(shí)間。
舉例:

setTimeout(function() {
       console.log("jirengu")
},1000);//返回1届良,一秒鐘后打印出jirengu

返回的整數(shù)表示這個(gè)定時(shí)器的編號(hào)笆凌,以后可以用來(lái)取消這個(gè)定時(shí)器,但實(shí)際任務(wù)中士葫,很少這么用乞而。

setTimeout函數(shù)的重點(diǎn)是第二個(gè)參數(shù),第二個(gè)參數(shù)是一個(gè)表示等待多長(zhǎng)時(shí)間的毫秒數(shù)慢显,但是經(jīng)過(guò)該時(shí)間的后執(zhí)行的代碼不一定會(huì)執(zhí)行爪模。

在理解這句話之前先說(shuō)說(shuō)JavaScript的運(yùn)行機(jī)制:
JavaScript是一個(gè)單線程的解釋器,一定時(shí)間之內(nèi)只能執(zhí)行一段代碼荚藻。
為了控制要執(zhí)行的代碼屋灌,就有一個(gè)JavaScript任務(wù)隊(duì)列。這些任務(wù)會(huì)按照將它們添加到隊(duì)列的順序執(zhí)行应狱。
setTimeout()的第二個(gè)參數(shù)告訴JavaScript再過(guò)多長(zhǎng)時(shí)間把當(dāng)前任務(wù)添加到隊(duì)列中共郭。也就是說(shuō)setTimeout()指定的任務(wù)肯定是最后一個(gè)添加到隊(duì)列中的,這個(gè)指定的任務(wù)要等到前面的任務(wù)執(zhí)行完了以后再執(zhí)行疾呻。
所以setTimeout函數(shù)的第二個(gè)參數(shù)應(yīng)該理解為等到前面的任務(wù)執(zhí)行之后再經(jīng)過(guò)指定的毫秒數(shù)后來(lái)執(zhí)行當(dāng)前的任務(wù)除嘹。
舉例來(lái)說(shuō)明吧:

console.log(1)
setTimeout(function() {
       console.log(2)
},100);
var t1 = Date.now()
for(var i=0;i<10000;i++){
      console.log(3);
}
var t2 = Date.now()
console.log(t2-t1);
運(yùn)行結(jié)果

從運(yùn)行結(jié)果中看到,console.log(2)確實(shí)是最后運(yùn)行岸蜗,而且是等到完成for循環(huán)的后再運(yùn)行的,而不是之前理解的100ms之后會(huì)立即運(yùn)行尉咕。

那么最后解釋setTimeout 0就比較容易了,指的是setTimeout指定的任務(wù)在現(xiàn)有的任務(wù)執(zhí)行之后立即執(zhí)行璃岳。

代碼題

1.下面的代碼輸出多少年缎?修改代碼讓fnArr[i]()輸出i.使用兩種以上的方法

    var fnArr = [];
    for (var i = 0; i < 10; i ++) {
        fnArr[i] =  function(){
            return i;
        };
    }
    console.log( fnArr[3]() );  //輸出結(jié)果為10

在for循環(huán)中悔捶,i的值并沒(méi)有隨著循環(huán)保存在函數(shù)中,所以關(guān)鍵在于如何保存i的值晦款,所以有了以下閉包的方法:

//方法一:
var fnArr = [];
for (var i =0; i<10; i++){
       fnArr[i] = (function(n){
            return function(){
                  return n;
            }
})(i)
}
console.log(fnArr[3]());

//方法二:
    var fnArr = [];
    for(var i=0; i<10; i++){
        (function(n){
            fnArr[n] = function(){
                return n;
            }
        })(i)
    }
    console.log(fnArr[3]());

2.使用閉包封裝一個(gè)汽車(chē)對(duì)象炎功,可以通過(guò)以下方式獲取汽車(chē)狀態(tài)

var Car = //todo;
Car.setSpeed(30);
Car.getSpeed(); //30
Car.accelerate();
Car.getSpeed(); //40;
Car.decelerate();
Car.decelerate();
Car.getSpeed(); //20
Car.getStatus(); // 'running';
Car.decelerate(); 
Car.decelerate();
Car.getStatus();  //'stop';
//Car.speed;  //error

實(shí)現(xiàn)代碼:

    var Car = (function(){
        var speed = 0;
        function setSpeed(){
            speed = arguments[0];
        }
        function getSpeed(){
            console.log(speed);
            return speed;
        }
        function accelerate(){
            speed += 10;
        }
        function decelerate(){
            speed -= 10;
        }
        function getStatus(){
            if(speed > 0){
                console.log("running");
                return "running";
            }else {
                console.log("stop");
                return "stop";
            }
        }
        return {
            "setSpeed":setSpeed,
            "getSpeed":getSpeed,
            "accelerate":accelerate,
            "decelerate":decelerate,
            "getStatus":getStatus
        }
    })()
    Car.setSpeed(30);
    Car.getSpeed(); //30
    Car.accelerate();
    Car.getSpeed(); //40;
    Car.decelerate();
    Car.decelerate();
    Car.getSpeed(); //20
    Car.getStatus(); // 'running';
    Car.decelerate();
    Car.decelerate();
    Car.getStatus();  //'stop';
運(yùn)行結(jié)果

3.寫(xiě)一個(gè)函數(shù)使用setTimeout模擬setInterval的功能

//方法一
    function interval(func,time){
        var intv = function(){
            func.call(null);
            setTimeout(intv,time);
        }
        setTimeout(interval,time);
    }

    interval(function(){
        console.log(1);
    },1000);


//方法二
    function interval(func, time){
        setTimeout(function(){
            func.call(null);
            interval(func,time);
        },time)
    }

    interval(function(){
        console.log(1);
    },1000)

需要注意的是,使用setTimeout并不能完全模擬出setInterval的功能缓溅。
在問(wèn)答1中介紹過(guò)蛇损,setTimeout是等前面的任務(wù)執(zhí)行之后再開(kāi)始計(jì)算時(shí)間間隔。
而setInterval函數(shù)指定的是“開(kāi)始執(zhí)行”之間的間隔坛怪,并不考慮每次任務(wù)執(zhí)行本身所消耗的時(shí)間淤齐,比如,setInterval指定每100ms執(zhí)行一次袜匿,每次執(zhí)行需要5ms更啄,那么第一次執(zhí)行結(jié)束后95毫秒,第二次執(zhí)行就會(huì)開(kāi)始居灯。如果某次執(zhí)行耗時(shí)特別長(zhǎng)祭务,比如需要105毫秒,那么它結(jié)束后怪嫌,下一次執(zhí)行就會(huì)立即開(kāi)始义锥。

4.寫(xiě)一個(gè)函數(shù),計(jì)算setTimeout平均最小時(shí)間粒度岩灭。

    function getMini() {
        var i = 0;
        var start = Date.now();
        var clock = setTimeout(function(){
            i++;
            if(i === 1000){
                clearTimeout(clocl);
                var stop = Date.now();
                console.log((stop-start/1000));
            }
            else{
                var clock = setTimeout(arguments.callee,0);
            }
        },0)
    }
    getMini();

5.下面這段代碼輸出結(jié)果是拌倍?為什么?

var a = 1;
setTimeout(function(){
    a = 2;
    console.log(a);
}, 0);
var a ;
console.log(a);
a = 3;
console.log(a);

由于setTimeout函數(shù)會(huì)把指定的任務(wù)放在最后執(zhí)行噪径,所以以上代碼實(shí)際執(zhí)行順序如下:

var a = 1;
var a ;
console.log(a);//1
a = 3;
console.log(a);//3
setTimeout(function(){
    a = 2;
    console.log(a);//2
}, 0);

所以最后的輸出結(jié)果為1,3,2.

6.下面這段代碼輸出結(jié)果是柱恤?為什么?

var flag = true;
setTimeout(function(){
    flag = false;
},0)
while(flag){}
console.log(flag);

while方法會(huì)無(wú)限循環(huán)找爱,無(wú)任何輸出梗顺。
同上題,setTimeout函數(shù)會(huì)把指定的任務(wù)放在最后執(zhí)行车摄,所以實(shí)際執(zhí)行順序如下:

var flag = true;
while(flag){}
console.log(flag);
setTimeout(function(){
    flag = false;
},0)

變量flag一直為true荚守,所以while方法會(huì)無(wú)限循環(huán)。

7.下面這段代碼輸出练般?如何輸出如何輸出delayer: 0, delayer:1...(使用閉包來(lái)實(shí)現(xiàn))

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

實(shí)現(xiàn)代碼:

//方法一
    for(var i=0; i<5; i++){
        (function(n){
            setTimeout(function(){
                console.log("delayer:" + n);
            },0)
        })(i);
        console.log(i);
    }
//方法二
     for(var i=0; i<5; i++){
         setTimeout((function(n){
             return function(){
                 return console.log("delayer:" + n);
             }
         })(i),0)
         console.log(i);
     }
運(yùn)行結(jié)果

本文版權(quán)歸本人和饑人谷所有,轉(zhuǎn)載請(qǐng)注明來(lái)源锈候。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末薄料,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子泵琳,更是在濱河造成了極大的恐慌摄职,老刑警劉巖誊役,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異谷市,居然都是意外死亡蛔垢,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)迫悠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)鹏漆,“玉大人,你說(shuō)我怎么就攤上這事创泄∫樟幔” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵鞠抑,是天一觀的道長(zhǎng)饭聚。 經(jīng)常有香客問(wèn)我,道長(zhǎng)搁拙,這世上最難降的妖魔是什么秒梳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮箕速,結(jié)果婚禮上酪碘,老公的妹妹穿的比我還像新娘。我一直安慰自己弧满,他們只是感情好婆跑,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著庭呜,像睡著了一般滑进。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上募谎,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天扶关,我揣著相機(jī)與錄音,去河邊找鬼数冬。 笑死节槐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拐纱。 我是一名探鬼主播铜异,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼秸架!你這毒婦竟也來(lái)了揍庄?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤东抹,失蹤者是張志新(化名)和其女友劉穎蚂子,沒(méi)想到半個(gè)月后沃测,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡食茎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年蒂破,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片别渔。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡附迷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钠糊,到底是詐尸還是另有隱情挟秤,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布抄伍,位于F島的核電站艘刚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏截珍。R本人自食惡果不足惜攀甚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岗喉。 院中可真熱鬧秋度,春花似錦、人聲如沸钱床。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)查牌。三九已至事期,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纸颜,已是汗流浹背兽泣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胁孙,地道東北人唠倦。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像涮较,于是被迫代替她去往敵國(guó)和親稠鼻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

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

  • 問(wèn)題 一、什么是閉包? 有什么作用? 1.什么是閉包①JavaScript高級(jí)程序設(shè)計(jì)第三版定義閉包是指有權(quán)訪問(wèn)另...
    鴻鵠飛天閱讀 463評(píng)論 0 0
  • 一毛肋、什么是閉包?有什么作用 什么是閉包閉包是定義在一個(gè)函數(shù)內(nèi)部的函數(shù)屋剑,它可以訪問(wèn)父級(jí)函數(shù)的內(nèi)部變量润匙。當(dāng)一個(gè)閉包被創(chuàng)...
    __Qiao閱讀 686評(píng)論 0 0
  • 問(wèn)題 1.什么是閉包? 有什么作用 JavaScript高級(jí)程序設(shè)計(jì)第三版定義閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的...
    Lily的夏天閱讀 413評(píng)論 0 0
  • 1.什么是閉包? 有什么作用 定義:閉包就是嵌套在函數(shù)里面的內(nèi)部函數(shù)巍膘,并且該內(nèi)部函數(shù)可以訪問(wèn)外部函數(shù)中聲明的所有局...
    饑人谷區(qū)子銘閱讀 918評(píng)論 0 2
  • 問(wèn)題 一峡懈、什么是閉包? 有什么作用璃饱? 閉包閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。在javascript中肪康,只有函...
    婷樓沐熙閱讀 576評(píng)論 0 0