JavaScript 閉包笆怠、定時(shí)器

閉包及其作用

  • 閉包是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)污淋;相當(dāng)于在草原上用柵欄單獨(dú)圍一片地只留一個(gè)進(jìn)出口;只有通過返回出的函數(shù)才能去修改其內(nèi)部的變量叶洞。
  • 有兩個(gè)作用:①讀取/修改其他函數(shù)內(nèi)部的變量鲫凶,形成單獨(dú)的一個(gè)空間,不受外部影響衩辟,可用于封裝螟炫。②使其他函數(shù)內(nèi)部的變量不會被銷毀而始終存在于內(nèi)存中。

setTimeout 0 的作用

  • setTimeout 0 的作用并不在于其延時(shí)0的這個(gè)字面意思艺晴,而是js對它的處理機(jī)制上昼钻;對被setTimeout包裹的代碼段,不管其延時(shí)多久封寞,都會被js放到代碼的尾部然评,只有等其他代碼執(zhí)行完畢后才會按延時(shí)時(shí)間去運(yùn)行其內(nèi)部的代碼;
  • 根據(jù)這個(gè)特性狈究,我們可以把需要最后執(zhí)行的代碼用setTimeout 0進(jìn)行包裹碗淌,確保最后執(zhí)行;在部分事件上抖锥,例如我需要一個(gè)div顯示用戶輸入文本框的內(nèi)容亿眠,這個(gè)時(shí)候我使用onkeydown來綁定更新輸入值,當(dāng)鍵盤被按下時(shí)開始更新輸入值磅废;但是第一次按下鍵盤輸入時(shí)纳像,此時(shí)js的處理結(jié)果還沒出來,但由于我綁定按下這個(gè)條件就會更新輸入值拯勉,所以等于第一次輸入去獲取更新時(shí)是空的竟趾,這樣在用戶看來就是我按下第二個(gè)鍵才顯示之前輸入的內(nèi)容;那么我們可以怎么做呢宫峦?對岔帽,在獲取更新的這個(gè)代碼上加setTimeout 0 ,讓其跑到j(luò)s處理結(jié)果之后去更新斗遏,這樣就能實(shí)時(shí)顯示輸入值了山卦!

小練習(xí)

下面的代碼輸出多少鞋邑?修改代碼讓fnArri 輸出 i

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

方法1 使用閉包:

var fnArr = [];
for (var i = 0; i < 10; i ++) {
    fnArr[i] =  function(i){
        return function(){
          return i;
        };
    }(i);
}
console.log( fnArr[2]() );  //  2

方法2 把i綁定到函數(shù)上 作為函數(shù)的一個(gè)屬性存儲起來

var fnArr = [];
for (var i = 0; i < 10; i ++) {
  var print=function(){};
  print.index=i;
  fnArr[i]=print;

}
console.log( fnArr[5].index );  //  5

方法3 用兩個(gè)立即執(zhí)行函數(shù)返回i 賦給fnArr[i]诵次;相當(dāng)于fnArr[i]=i账蓉,數(shù)組里面放的是固定的數(shù)(好像沒什么。逾一。铸本。但是fnArr[i]可以輸出i)

var fnArr = [];
for (var i = 0; i < 10; i ++) {
    fnArr[i] =  function(){
        return function(){
          return i;
        }();
    }();
}
console.log( fnArr[7] );  //  7

使用閉包封裝一個(gè)car對象

var Car = function(){
  var speed=0;
  return{
    setSpeed:function (num){
      speed=num;
    },
    getSpeed:function (){
      console.log(speed);
    },
    accelerate:function (){
      speed=speed+10;
    },
    decelerate:function (){
      speed=speed-10;
    },
    getStatus:function (){
      if(speed>0)
        console.log('running')
      else console.log('stop')
    }
  }
}();
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

使用setTimeout模擬setInterval的功能

function newInterval(func,time){  //定義偽間隔函數(shù)  一個(gè)形參為‘函數(shù)’,另一個(gè)形參為‘間隔時(shí)間’
  setTimeout(function(){
    func();
    newInterval(func,time);
  },time);
}
var i=1;
function count(){      //舉個(gè)例子 使用計(jì)數(shù)函數(shù) 
  console.log(i++);
}
newInterval(count,1000);

計(jì)算setTimeout最小時(shí)間粒度

function min(){
  var t1=Date.now();
  var i=0;
  var clock=setTimeout(function(){
    i++;
    if (i==5000){
      clearInterval(clock);
      console.log((Date.now()-t1)/i);
    }
    clock=setTimeout(arguments.callee,0)
  },0);
}
min();  //  4.102  4.0982  4.0968  最小粒度應(yīng)該為4ms 

解釋如下代碼的輸出

var flag = true;
setTimeout(function(){
    flag = false;
},0)
while(flag){}   //沒有輸出結(jié)果 因?yàn)閟etTimeout所包裹的代碼將會被放到末尾執(zhí)行 flag一直是true 導(dǎo)致循環(huán)一直在進(jìn)行遵堵,后面的代碼在排隊(duì)等候中
console.log(flag); 

下面這段代碼輸出箱玷?如何輸出delayer: 0, delayer:1...(使用閉包來實(shí)現(xiàn))

for(var i=0;i<5;i++){
    setTimeout(function(){
         console.log('delayer:' + i );  // 
    }, 0);
    console.log(i);    // 先輸出 0  1  2  3  4 ,再輸出 delayer:5
}

讓其輸出delayer: 0, delayer:1的方法如下:

for(var i=0;i<5;i++){
  (function(i){
    setTimeout(function(){
      console.log('delayer:' + i );
    }, 0);
    console.log(i);   //先輸出 0  1  2  3   4 再輸出 delayer:0 delayer:1 delayer:2 delayer:3 delayer:4
  })(i);                    
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陌宿,一起剝皮案震驚了整個(gè)濱河市锡足,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌壳坪,老刑警劉巖舶得,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異爽蝴,居然都是意外死亡沐批,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門蝎亚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來九孩,“玉大人,你說我怎么就攤上這事发框√杀颍” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵梅惯,是天一觀的道長顾患。 經(jīng)常有香客問我,道長个唧,這世上最難降的妖魔是什么江解? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮徙歼,結(jié)果婚禮上犁河,老公的妹妹穿的比我還像新娘。我一直安慰自己魄梯,他們只是感情好桨螺,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酿秸,像睡著了一般灭翔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辣苏,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天肝箱,我揣著相機(jī)與錄音哄褒,去河邊找鬼。 笑死煌张,一個(gè)胖子當(dāng)著我的面吹牛呐赡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播骏融,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼链嘀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了档玻?” 一聲冷哼從身側(cè)響起怀泊,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎误趴,沒想到半個(gè)月后包个,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冤留,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年碧囊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纤怒。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡糯而,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泊窘,到底是詐尸還是另有隱情熄驼,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布烘豹,位于F島的核電站瓜贾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏携悯。R本人自食惡果不足惜祭芦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望憔鬼。 院中可真熱鬧龟劲,春花似錦、人聲如沸轴或。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽照雁。三九已至蚕愤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萍诱。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工悬嗓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砂沛。 一個(gè)月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓烫扼,卻偏偏與公主長得像曙求,于是被迫代替她去往敵國和親碍庵。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359

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