進階11:閉包_定時器_BOM

題目1: 下面的代碼輸出多少?修改代碼讓 fnArr[i]()輸出i钉迷。使用 兩種以上的方法

var fnArr = [];
    for (var i = 0; i < 10; i ++) {
        fnArr[i] =  function(){
            return i;
        };
    }
    console.log( fnArr[3]() );           //打印出10 
/*
因為當i自增到10,才跳出for循環(huán),然后開始執(zhí)行fnArr[3](),匿名函數(shù)function(){return i;} 此時才被調(diào)用,
調(diào)用的時候i=10,所以返回10.
*/

解決辦法:

//方法1:
for (var i = 0; i < 10; i++) {
    fnArr[i] = (function(i){    //這個括號里的i是自有變量,與外部for里的i毫無關(guān)聯(lián),只受傳入的參數(shù)影響
        return function(){     //返回一個函數(shù)function(){}
            return i;
        };
    })(i);  //這個i為外部傳入的參數(shù)
}
console.log(fnArr[3]()) //打印結(jié)果為3.  
//注意這里fnArr[3]()能調(diào)用,說明fnArr[i]是個函數(shù),所以上面需要需要返回一個函數(shù)function(){}
//方法2:
for (var i = 0; i < 10; i++) {
    (function(i){
       fnArr[i] = function(){
         return i;
       }
    })(i)
}
console.log(fnArr[3]()) //打印結(jié)果為3.  
//方法3:
for (let i = 0; i < 10; i++) {    //let 語句聲明一個塊級作用域的本地變量
  fnArr[i] = function(){
    return i;
  };
}
console.log(fnArr[3]());                   //打印結(jié)果為3

總結(jié):

  • 可以用立即表達式的方式在內(nèi)部再聲明一個內(nèi)部自有變量,形成新的作用域阻隔變量提升,來解決因為變量提升所產(chǎn)生的問題

題目2: 封裝一個汽車對象抓韩,可以通過如下方式獲取汽車狀態(tài)

var Car = (function(){
   var speed = 0;
   function setSpeed(s){
       speed = s
   }
  /* 補充*/
  function getSpeed(){
       return speed;
  }
  function accelerate(){
      speed += 10;
  }
  function decelerate(){
     if(speed >= 10){
           speed -= 10;
    }else{
      console.log('減速幅度大于當前最低速度,無法減速')
    }
  }
function getStatus(){
    if(speed > 0){
     console.log('running');
    }else{
     console.log('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';
//Car.speed;  //error

測試

題目3:下面這段代碼輸出結(jié)果是? 為什么?

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

解題思路:

//聲明前置
var a;
var a ;
a = 1;
setTimeout(function(){
    a = 2;
    console.log(a);     //打印出2,但是由于setTimeout運行機制,需等到所有代碼執(zhí)行完,才會執(zhí)行
}, 0);
console.log(a);   //打印出1,因為上面a被賦值為1
a = 3;   
console.log(a);  //打印出3,因為上面a被賦值為3

因為定時器的運行機制:將指定的代碼移出本次執(zhí)行,等到下一輪 Event Loop 時,再檢查是否到了指定時間痢站。如果到了,就執(zhí)行對應的代碼选酗;如果不到阵难,就等到再下一輪 Event Loop 時重新判斷時間

所以最終打印順序及結(jié)果是

1
3
2

題目4:下面這段代碼輸出結(jié)果是? 為什么?

var flag = true;
setTimeout(function(){   //由于setTimeout運行機制,要等到所有代碼執(zhí)行完,才會被執(zhí)行,所以這里也永遠不被執(zhí)行
    flag = false;
},0)
while(flag){}    /*while循環(huán)的特性,只要指定條件是true,循環(huán)就可以一直執(zhí)行代碼.因為flag為true,while無限循環(huán),不會執(zhí)行之后的代碼*/
console.log(flag); //不被執(zhí)行

代碼沒有任何輸出

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

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

整理以上代碼:聲明提前,setTimeout代碼執(zhí)行置后

var i
for(i=0;i<5;i++){
    console.log(i); //因為定時器執(zhí)行機制, 所以此行優(yōu)先執(zhí)行,先輸出0 1 2 3 4
    setTimeout(function(){
         console.log('delayer:' + i );  //執(zhí)行完所有代碼后開始執(zhí)行,i已經(jīng)自增到5,因為只有一個全局變量i,此時i的值為5,所以輸出5次 delayer:5
    }, 0);  
}

解題思路:可以在函數(shù)內(nèi)部再聲明一個內(nèi)部變量

for(var i=0;i<5;i++){
     (function(i){     //這個i是函數(shù)自有變量 ,與外部變量i不是同一個變量,不受for循環(huán)里的i值影響,只受傳入的參數(shù)i影響
     setTimeout(function(){
         console.log('delayer:' + i ); // 這里的i也是自有內(nèi)部變量,當所有代碼執(zhí)行完后,開始執(zhí)行,傳入?yún)?shù)依次是0 1 2 3 4
    }, 0);
    console.log(i);
    })(i); //i為傳入?yún)?shù) 傳入?yún)?shù)依次是 0 1 2 3 4
}

所以最終輸出結(jié)果是:

0
1
2
3
4
delayer:0
delayer:1
delayer:2
delayer:3
delayer:4

題目6: 如何獲取元素的真實寬高

主流瀏覽器通過window.getComputedStyle來獲取真實style芒填,低版本IE通過element.currentStyle來獲取真實style

   <style>
     .box{
         border: 3px solid red;
         height: 300px;
         width: 500px;
     }
   </style>
    
   <div class="box"></div>

   <script>
        var box = document.querySelector('.box')    //獲取元素節(jié)點

        //獲取元素的真實style
        function trueStyle(element,pseudoElt){
            return element.currentStyle ? element.currentStyle : window.getComputedStyle(element,pseudoElt);
        }
        var tureWidth = trueStyle(box).width;
        var trueHeight = trueStyle(box).height;

題目7: URL 如何編碼解碼呜叫?為什么要編碼?

  • 編碼方式:
    encodeURI()
    encodeURIComponent()
    區(qū)別:
    encodeURI方法不會對下列字符編碼 ASCII字母殿衰、數(shù)字朱庆、~!@#$&*()=:/,;?+'
    encodeURIComponent方法不會對下列字符編碼 ASCII字母、數(shù)字闷祥、~!*()'
    所以encodeURIComponent比encodeURI編碼的范圍更大娱颊。

  • 解碼方式:
    decodeURI()
    decodeURIComponent()

  • 編碼原因:

對于Url來說,之所以要進行編碼,是因為Url中有些字符會引起歧義箱硕。
比如說“name1=value1”,其中value1的值是“va&lu=e1”字符串拴竹,那么實際在傳輸過程中就會變成這樣“name1=va&lu=e1”。我們的本意是就只有一個鍵值對剧罩,但是服務端會解析成兩個鍵值對栓拜,這樣就產(chǎn)生了歧義。
又如斑响,Url的編碼格式采用的是ASCII碼菱属,而不是Unicode,這也就是說你不能在Url中包含任何非ASCII字符舰罚,例如中文纽门。否則如果客戶端瀏覽器和服務端瀏覽器支持的字符集不同的情況下,中文可能會造成問題营罢。
URL編碼的原則就是使用安全的字符(沒有特殊用途或者特殊意義的可打印字符)去表示那些不安全的字符.
預備知識:URI是統(tǒng)一資源標識的意思赏陵,通常我們所說的URL只是URI的一種。下面提到的URL編碼饲漾,實際上應該指的是URI編碼蝙搔。
[參考]https://www.cnblogs.com/jerrysion/p/5522673.html


題目8補全如下函數(shù),判斷用戶的瀏覽器類型

function isAndroid() {
    return /android/i.test(navigator.userAgent)
}
function isIphone(){
    return /iphone/i.test(navigator.userAgent)
}
function isIpad() {
    return /ipad/i.test(navigator.userAgent)
}
function isIOS() {
    return /iphone|ipad/i.test(navigator.userAgent)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末考传,一起剝皮案震驚了整個濱河市吃型,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌勤晚,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泉褐,死亡現(xiàn)場離奇詭異赐写,居然都是意外死亡挺邀,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門夕膀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耻煤,“玉大人攘已,你說我怎么就攤上這事【绶溃” “怎么了狮暑?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長歉糜。 經(jīng)常有香客問我伞辛,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮蓬网,結(jié)果婚禮上锯厢,老公的妹妹穿的比我還像新娘馍佑。我一直安慰自己,他們只是感情好萍摊,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布挤茄。 她就那樣靜靜地躺著,像睡著了一般冰木。 火紅的嫁衣襯著肌膚如雪穷劈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天踊沸,我揣著相機與錄音歇终,去河邊找鬼。 笑死逼龟,一個胖子當著我的面吹牛评凝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腺律,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼奕短,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了匀钧?” 一聲冷哼從身側(cè)響起翎碑,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎之斯,沒想到半個月后日杈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡佑刷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年莉擒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘫絮。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡涨冀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出麦萤,到底是詐尸還是另有隱情蝇裤,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布频鉴,位于F島的核電站,受9級特大地震影響恋拍,放射性物質(zhì)發(fā)生泄漏垛孔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一施敢、第九天 我趴在偏房一處隱蔽的房頂上張望周荐。 院中可真熱鬧狭莱,春花似錦、人聲如沸概作。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讯榕。三九已至骤素,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愚屁,已是汗流浹背济竹。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留霎槐,地道東北人送浊。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像丘跌,于是被迫代替她去往敵國和親袭景。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

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

  • 1: 下面的代碼輸出多少闭树?修改代碼讓 fnArr[i]() 輸出 i耸棒。使用 兩種以上的方法 方法1:聲明個函數(shù),創(chuàng)...
    曉風殘月1994閱讀 382評論 0 0
  • 題目1: 下面的代碼輸出多少蔼啦?修改代碼讓fnArri 輸出 i榆纽。使用兩種以上的方法 題目2: 封裝一個汽車對象,可...
    饑人谷_桶飯閱讀 399評論 0 0
  • 題目1: 下面的代碼輸出多少捏肢?修改代碼讓 fnArri 輸出 i奈籽。使用 兩種以上的方法 方法一: 方法二: 題目2...
    我七閱讀 313評論 0 0
  • 題目1: 下面的代碼輸出多少?修改代碼讓 fnArri 輸出 i鸵赫。使用 兩種以上的方法 方法一: 方法二: 方法三...
    南山碼農(nóng)閱讀 280評論 0 1
  • ??? 2017.12.11 寫給小馬哥的一封信衣屏。其實這算是一封情書啦!先來介紹一下辩棒,這位小馬哥呢狼忱,是我喜...
    小胖胖仙女兒閱讀 157評論 2 2