進(jìn)階11 閉包_定時(shí)器_BOM

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

    var fnArr = [];
    for (var i = 0; i < 10; i ++) {
        fnArr[i] =  function(){
            return i; // 后面調(diào)用函數(shù)去執(zhí)行的時(shí)候,這里的 i 實(shí)際上已經(jīng)是全局的i盏浇,已經(jīng)經(jīng)過(guò)了10次循環(huán)
        };
    }
    console.log( fnArr[3]() );  //輸出10

方法1:聲明個(gè)函數(shù)嘀韧,創(chuàng)建新的作用域并立即執(zhí)行,從而每次給數(shù)組fnArr賦不同的函數(shù)

  var fnArr = []
  for (var i = 0; i < 10; i ++) {
    !function(i){ // 這里的 i 只是形參缠捌,可以是任何其他名字锄贷,函數(shù)內(nèi)部使用相同名字即可
      fnArr[i] =  function(){
        return i // 后面調(diào)用函數(shù)去執(zhí)行的時(shí)候,這里的 i 實(shí)際上已經(jīng)是全局的i曼月,已經(jīng)經(jīng)過(guò)了10次循環(huán)
      }
    }(i) // 每一次循環(huán)谊却,都會(huì)執(zhí)行函數(shù),傳入的不同的 i
  }
  console.log( fnArr[3]() );  //輸出10

方法2:

  //方法2 使用自動(dòng)執(zhí)行函數(shù)哑芹,返回的是原來(lái)的函數(shù)炎辨,但自動(dòng)執(zhí)行函數(shù)每一次循環(huán)時(shí)傳入的 i 都不一樣
  var fnArr = [];
  for (var i = 0; i < 10; i ++) {
    fnArr[i] =  function(i){
      return function(){
        return i; //所以這里的i,在循環(huán)時(shí)傳入的是什么值聪姿,五百年后調(diào)用出來(lái)還是什么值碴萧,不會(huì)自增
      }
    }(i)
  }
  console.log( fnArr[3]() ); 

以上兩種方法都可以,造成問(wèn)題的原因就是閉包末购,函數(shù)內(nèi)訪(fǎng)問(wèn)了外部的變量破喻,而外部變量的值在函數(shù)執(zhí)行的時(shí)候早已塵埃落地。
所以解決問(wèn)題的關(guān)鍵就是使用立即執(zhí)行函數(shù):在循環(huán)的時(shí)候盟榴,就做點(diǎn)手腳曹质,通過(guò)再‘包’一層函數(shù),隔斷閉包擎场,構(gòu)建新的函數(shù)作用域羽德,并立即執(zhí)行,把每次自增的 i 都挨個(gè)傳入函數(shù)的局部作用域內(nèi)迅办,賦給新的變量宅静。
這樣最后調(diào)用函數(shù)的時(shí)候,能看似得到fnArr[i]() 輸出 i , 但實(shí)際上這里輸出的 i 早已經(jīng)不是當(dāng)年的 i 站欺,當(dāng)年的 i 循環(huán)完了就已經(jīng)變成10了姨夹,不信的話(huà)究驴, console.log(i) 便知。

方法3:

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

只修改一個(gè)地方匀伏,把for循環(huán)中的var i 換成 let i 構(gòu)成塊級(jí)變量洒忧,從而在一開(kāi)始,就避免了i 是全局變量所帶來(lái)的問(wèn)題——return i 這里的 i 每次調(diào)用時(shí)够颠,都指向循環(huán)結(jié)束后的 i 熙侍,也就是 10 。
let 使得 for每次循環(huán)履磨,其塊內(nèi)都會(huì)生成一個(gè)塊級(jí)作用域蛉抓,所以4個(gè)事件處理函數(shù),也就是console.log(i) 就綁定指向了不同的 i 剃诅。

2: 封裝一個(gè)汽車(chē)對(duì)象巷送,可以通過(guò)如下方式獲取汽車(chē)狀態(tài)

var Car = (function(){
   var speed = 0;
   function setSpeed(s){
       speed = s
   }
   ...
   return {
      setSpeed: setSpeed,
      ...
   }
})()
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

做法如下:

  var Car = (function(){
    var speed = 0;
    function setSpeed(s){
      speed = s
    }
    function getSpeed(){
      return speed
    }
    function accelerate(){
      speed += 10
    }
    function decelerate(){
      if(speed !== 0){
        speed -= 10
      }
    }
    function getStatus(){
      return (speed === 0)?'stop':'running'
    }
    return {
      // 返回對(duì)象的屬性是方法(如果一個(gè)屬性的值為函數(shù),通常把這個(gè)屬性稱(chēng)為“方法”)
      setSpeed: setSpeed, // 這里屬性名和值不一定要一樣矛辕,也可以把上面的方法函數(shù)匿名寫(xiě)在這里
      getSpeed: getSpeed,
      accelerate: accelerate,
      decelerate: decelerate,
      getStatus: getStatus
    }
 })() //Car立即執(zhí)行后返回的是對(duì)象笑跛,對(duì)象里存的方法

 //對(duì)象.方法()
 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 這樣是get不到speed的,speed是被封裝在函數(shù)里的變量聊品,只能用提供的方法間接訪(fǎng)問(wèn)

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

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

因?yàn)槎〞r(shí)器會(huì)被異步執(zhí)行飞蹂,0代表 立刻進(jìn)入任務(wù)隊(duì)列中,但是具體執(zhí)行翻屈,要先看主進(jìn)程是否執(zhí)行完畢陈哑,再看任務(wù)隊(duì)列前面是否還有其他任務(wù)。 所以 0 只是代表盡可能快地的被執(zhí)行

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

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

注定沒(méi)結(jié)果伸眶。 無(wú)限死循環(huán)惊窖,CPU瞬間100%峰值。
因?yàn)槎〞r(shí)器永遠(yuǎn)不會(huì)被執(zhí)行厘贼,會(huì)被放入任務(wù)隊(duì)列中界酒,先去執(zhí)行的是while,flag 永遠(yuǎn)都是true, 后面的console.log(flag)也不會(huì)輸出

5: 下面這段代碼輸出涂臣?如何輸出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);
}
輸出 0 1 2 3 4  delayer: 5 delayer: 5 delayer: 5 delayer: 5 delayer: 5

做法參考第一題:

for(var i=0;i<5;i++){
    //每次循環(huán)盾计,分別傳入 0 1 2 3  4  
    setTimeout(function(i){
    //這里的參數(shù) i 作用域只在當(dāng)前函數(shù),不再是之前的i赁遗,參數(shù)傳進(jìn)來(lái)的時(shí)候,相當(dāng)于內(nèi)部的 i 分別賦值
      return function(){
        console.log('delayer:' + i );
      }
    }(i), 0);
    console.log(i);
}

6: 如何獲取元素的真實(shí)寬高

第一種情況就是寬高都寫(xiě)在樣式表里:

就比如#div1{width:120px;}族铆。這種情況通過(guò)#div1.style.width拿不到寬度岩四,而通過(guò)#div1.offsetWidth或者#div1.clientWidth才可以獲取到寬度(前者包含padding、border和滾動(dòng)條哥攘,后者包含padding不包含border和滾動(dòng)條)剖煌。

或者使用 getComputedStyle($('div')).width (這里的寬度材鹦,如果沒(méi)設(shè)置盒模型,那么就是content寬度耕姊,如果有box-sizing: border-box; 那么width就包含padding和border),在低版本IE中對(duì)應(yīng)的實(shí)現(xiàn)方法是:element.currentStyle

第二種情況就是寬和高是寫(xiě)在行內(nèi)中:

比如style="width:120px;"桶唐,這中情況通過(guò)上述3個(gè)方法都能拿到寬度。

注意如果不是寫(xiě)在行內(nèi)style中的屬性都不能通過(guò)id.style.atrr來(lái)獲取茉兰。

7: URL 如何編碼解碼尤泽?為什么要編碼?

JavaScript提供四個(gè)URL的編碼/解碼方法:

decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()

區(qū)別:

  • encodeURI方法不會(huì)對(duì)下列字符編碼:
    • ASCII字母
    • 數(shù)字
    • ~!@#$&*()=:/,;?+'
  • encodeURIComponent方法不會(huì)對(duì)下列字符編碼:
    • ASCII字母
    • 數(shù)字
    • ~!*()'

所以encodeURIComponent比encodeURI編碼的范圍更大规脸。

encodeURI和encodeURIComponent的區(qū)別在于前者被設(shè)計(jì)來(lái)用于對(duì)完整URL進(jìn)行URL Encode坯约,于是URL中的功能字符,比如&, ?, /, =等等這些并不會(huì)被轉(zhuǎn)義莫鸭;而后者被設(shè)計(jì)來(lái)對(duì)一個(gè)URL中的值進(jìn)行轉(zhuǎn)義嘁傀,會(huì)把這些功能字符也進(jìn)行轉(zhuǎn)義锐锣。應(yīng)用場(chǎng)景最常見(jiàn)的一個(gè)是手工拼URL的時(shí)候,對(duì)每對(duì)KV(鍵值)用encodeURIComponent進(jìn)行轉(zhuǎn)義。

一個(gè)直觀的例子坚踩,你隨便找個(gè)URL,用encodeUR轉(zhuǎn)換一下捡硅,然后paste到瀏覽器地址欄荐捻,回車(chē)發(fā)現(xiàn)依然可以訪(fǎng)問(wèn),而用encodeURIComponent轉(zhuǎn)換后蛋欣,則會(huì)被瀏覽器認(rèn)為你是要搜索航徙。

參考知乎Jim Liu的回答

為什么需要編碼呢?

之所以要進(jìn)行編碼陷虎,是因?yàn)閁RL中有些字符會(huì)引起歧義到踏,比如URL中的參數(shù)字符串,如果包含了=或者&尚猿,就會(huì)造成服務(wù)器解析錯(cuò)誤窝稿,因此要進(jìn)行轉(zhuǎn)義,也就是編碼凿掂。
再比如 URL格式采用的ASCII碼伴榔,而不是Unicode,如果URL中有非ASCII字符庄萎,比如漢字踪少,不轉(zhuǎn)碼也會(huì)出現(xiàn)問(wèn)題。
當(dāng)然在瀏覽器的地址欄你所看到的中文糠涛,實(shí)際上傳輸時(shí)經(jīng)過(guò)了轉(zhuǎn)換援奢,只是瀏覽器用了UTF-8的字符集展示給你,或者在當(dāng)前頁(yè)面F12打開(kāi)控制臺(tái)輸入 location.href 看一下當(dāng)前URL忍捡,就是經(jīng)過(guò)編碼后的集漾。

8: 補(bǔ)全如下函數(shù)切黔,判斷用戶(hù)的瀏覽器類(lèi)型

function isAndroid(){
}
funcnction isIphone(){
}
function isIpad(){
}
function isIOS(){
}

主要的思路就是 navigator.userAgent 方法的使用:

      function isAndroid() {
        if(navigator.userAgent.indexOf('Android') > -1){ //如果匹配到就返回index索引值,否則返回 -1
          return '這是Android瀏覽器'
        }
      }
      function isIphone(){
        if(/iPhone/.test(navigator.userAgent)){ //使用正則 reg.test(str) ,如果匹配就返回true具篇,否則返回false
          return '這是Iphone瀏覽器'
        }
      }
      function isIpad(){
        if(/iPad/.test(navigator.userAgent)){
          return '這是Ipad瀏覽器'
        }
      }
      function isIOS(){
        if(/iPhone|iPad/.test(navigator.userAgent)){
          return '這是IOS瀏覽器'
        }
      }
      // 可以使用chrome 的device 設(shè)備模擬纬霞,來(lái)試驗(yàn)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市驱显,隨后出現(xiàn)的幾起案子诗芜,更是在濱河造成了極大的恐慌,老刑警劉巖秒紧,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绢陌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡熔恢,警方通過(guò)查閱死者的電腦和手機(jī)脐湾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)叙淌,“玉大人秤掌,你說(shuō)我怎么就攤上這事∮セ簦” “怎么了闻鉴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)茂洒。 經(jīng)常有香客問(wèn)我孟岛,道長(zhǎng),這世上最難降的妖魔是什么督勺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任渠羞,我火速辦了婚禮,結(jié)果婚禮上智哀,老公的妹妹穿的比我還像新娘次询。我一直安慰自己,他們只是感情好瓷叫,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布屯吊。 她就那樣靜靜地躺著,像睡著了一般摹菠。 火紅的嫁衣襯著肌膚如雪盒卸。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,255評(píng)論 1 308
  • 那天辨嗽,我揣著相機(jī)與錄音世落,去河邊找鬼。 笑死糟需,一個(gè)胖子當(dāng)著我的面吹牛屉佳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洲押,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼武花,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了杈帐?” 一聲冷哼從身側(cè)響起体箕,我...
    開(kāi)封第一講書(shū)人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挑童,沒(méi)想到半個(gè)月后累铅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡站叼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年娃兽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尽楔。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡投储,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阔馋,到底是詐尸還是另有隱情玛荞,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布呕寝,位于F島的核電站勋眯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏下梢。R本人自食惡果不足惜客蹋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怔球。 院中可真熱鬧嚼酝,春花似錦、人聲如沸竟坛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)担汤。三九已至涎跨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崭歧,已是汗流浹背隅很。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留率碾,地道東北人叔营。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓屋彪,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親绒尊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子畜挥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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

  • 題目1: 下面的代碼輸出多少?修改代碼讓 fnArri 輸出 i婴谱。使用 兩種以上的方法 方法一: 方法二: 題目2...
    我七閱讀 314評(píng)論 0 0
  • 題目1: 下面的代碼輸出多少蟹但?修改代碼讓fnArri 輸出 i。使用兩種以上的方法 題目2: 封裝一個(gè)汽車(chē)對(duì)象谭羔,可...
    饑人谷_桶飯閱讀 399評(píng)論 0 0
  • 1. 使用立即執(zhí)行函數(shù)生成閉包华糖,利用其內(nèi)部函數(shù)讀取該函數(shù)局部作用域3種方式生成閉包 2.輸出汽車(chē)參數(shù)的函數(shù) 3.s...
    24_Magic閱讀 364評(píng)論 0 0
  • 題目1: 下面的代碼輸出多少?修改代碼讓 fnArri 輸出 i瘟裸。使用 兩種以上的方法 方法一: 方法二: 方法三...
    南山碼農(nóng)閱讀 286評(píng)論 0 1
  • 原創(chuàng)日記(4) 有個(gè)人跟我聊天客叉,沒(méi)聊幾句就問(wèn)我相信網(wǎng)友嗎?我說(shuō)有的網(wǎng)友可信有的不可信景描。然后他就說(shuō)如果我相信他就去考...
    黑金公主閱讀 131評(píng)論 0 1