閉包-for循環(huán)取值的解決方法

****閉包****
1.閉包應(yīng)該是指一個閉包域瓷产,每當(dāng)聲明一個函數(shù)時就產(chǎn)生了一個閉包域——這里可以解釋為每個函數(shù)都有自己的函數(shù)棧——每個閉包域(Function對象)都有一個function scope(這里的function scope不是屬性)鸟蜡,function scope內(nèi)默認(rèn)有一個Globe的全局引用,這個引用可以直接調(diào)用Globe的屬性或者方法包各。

2.外部無法訪問在閉包域內(nèi)聲明的變量或者方法那伐,閉包域可以訪問外部的變量或者方法。

3.當(dāng)一個閉包域內(nèi)包含另一個閉包域時(一個函數(shù)內(nèi)有另一個函數(shù)应又,內(nèi)部函數(shù)的生命周期依賴于外部函數(shù))宙项,若子閉包域(內(nèi)部函數(shù))使用了父閉包域(外部函數(shù))的私有變量(在父閉包域中聲明的變量,父閉包域的外部空間無法直接訪問株扛,但子閉包域可以訪問)尤筐,子閉包域(當(dāng)前的子函數(shù))的function scope會產(chǎn)生一個closure對象屬性,這個對象屬性內(nèi)包含的是子閉包域?qū)Ω搁]包域的所有引用(只要子閉包域還存活洞就,則父閉包域就依舊存活)如果在父閉包域存活期間對私有變量進(jìn)行修改盆繁,那么子閉包域?qū)Ω搁]包域私有變量的引用中function scope的closure對象屬性的內(nèi)容也會發(fā)生變化。

以下代碼中原本是想每次點擊對應(yīng)的目標(biāo)彈出對應(yīng)的數(shù)字下標(biāo)0-4旬蟋,但實際上無論點擊哪個目標(biāo)都會彈出數(shù)字5

<!DOCTYPE html>
<html lang="en">
<head>
      <meta charset="utf-8">
      <title></title>
      <script type="text/javascript">
                function onMyLoad(){
                     var arr = document.getElementsByTagName("p");
                     for(var i = 0; i < arr.length; i++){
                            arr[i].onclick = function(){
                                  alert(i);
                            }
                     }
                }
       </script>
</head>
<body onload="onMyLoad()">
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
</body>
</html>

上面點擊時油昂,arr中每一項的onclick均為一個函數(shù)實例(Function對象),這個函數(shù)實例產(chǎn)生一個閉包域倾贰,這個閉包域引用了外部閉包域的變量秕狰,其function scope的closure對象有個名為i的引用,外部閉包域的私有變量內(nèi)容發(fā)生變化時內(nèi)部閉包得到的值就會改變躁染。

1)上面代碼出現(xiàn)的問題第一種解決辦法:增加若干個對應(yīng)的閉包域空間(采用匿名函數(shù)實現(xiàn))專門用來存儲原先需要引用的內(nèi)容(下標(biāo)值)鸣哀,只限于基本類型(基本類型值傳遞,對象類型引用傳遞)

//聲明一個匿名函數(shù)吞彤,若傳進(jìn)來的是基本類型則為值傳遞我衬,不會對實參影響
for(var i = 0; i<arr.length; i++){
       (function (arg){//這個函數(shù)對象有一個本地私有變量arg(形參)叹放,該函數(shù)的function scope的closure對象屬性有兩個引用:arr和i。i的值隨外部改變挠羔,但是本地的私有變量(形參)arg不會受影響井仰,其值在一開始被調(diào)用時就決定了
            arr[i].onclick = function () {//onclick函數(shù)實例的function scope的closure對象屬性有一個引用arg
                  alert(arg);//只要外部空間的arg不變,這里的引用值就不會改變
            }
       })(i);//立即執(zhí)行匿名函數(shù)破加,傳遞下標(biāo)i(實參)
}

2)第二種解決方法:將下標(biāo)作為對象屬性(name:"i",value:i的值)添加到每個數(shù)組項(p對象)中

for(var i=0; i<arr.length; i++){
       //為當(dāng)前數(shù)組項(當(dāng)前p對象)添加一個名為i的屬性俱恶,值為循環(huán)體i變量的值
       //此時當(dāng)前p對象的i屬性并不是對循環(huán)體的i變量的引用,而是一個獨立p對象的屬性范舀,屬性值在聲明的時候就確定了
       arr[i].i = i;
       arr[i].onclick = function (){
              alert(this.i);
       }
}

3)第三種解決方法:增加若干個對應(yīng)的閉包域空間用來存儲下標(biāo)合是。新增的匿名閉包空間內(nèi)完成事件綁定。

//綁定的函數(shù)中的function scope中的closure對象的引用arg是指向?qū)⑵浞祷氐哪涿瘮?shù)的私有變量arg
for(var i = 0; i<arr.length; i++){
        arr[i].onclick = (function(arg){
                return function () {
                       alert(arg);
                }
        })(i);
}

4)第四種解決方法:跟第一種方法類似

for(var i = 0; i<arr.length; i++){
       (function(){
            var temp = i;
            arr[i].onclick = function (){
                  alert(temp);
            }
       })();
}

5)第五種解決方法:跟第三種方法和第四種方法類似

for(var i = 0; i<arr.length; i++){
      arr[i].onclick = (function () {
             var temp = i;
             return function () {
                   alert(temp);
             }
      })();
}

6)第六種解決方法:將下標(biāo)添加為綁定函數(shù)的屬性

for(var i = 0; i<arr.length; i++){
      (arr[i].onclick = function () {
             alert(arguments.callee.i);//arguments參數(shù)對象
      }).i = i;
}

7)第七中解決方法:通過new使用Function構(gòu)造函數(shù)創(chuàng)建Function實例锭环,傳入函數(shù)體的內(nèi)容是字符串聪全,所以Function得到的是一個字符串拷貝,而沒有得到i的引用辅辩。先獲取i.toString()然后與前后字符串拼接成一個新的字符串难礼,F(xiàn)unction對其方向解析成JS代碼。

for(var i = 0; i<arr.length; i++){
      arr[i].onclick = new Function("alert("+i+");");//每new一個Function得到一個Function對象(一個函數(shù))玫锋,有自己的閉包域
}

8)第8種解決方法:直接通過Function返回一個函數(shù)蛾茉。第七種解決方法中使用了new,使用了new撩鹿,那么Function函數(shù)就被當(dāng)成構(gòu)造器可以用來構(gòu)造一個Function實例返回谦炬。這種方法中不使用new,將Function函數(shù)當(dāng)成一個函數(shù)三痰,傳入?yún)?shù)返回一個新函數(shù)吧寺。

//使用了new,F(xiàn)unction函數(shù)充當(dāng)構(gòu)造器散劫,由JS解析器產(chǎn)生一個新的對象稚机,構(gòu)造器內(nèi)的this指向該新對象
//不使用new,F(xiàn)unction函數(shù)依舊是函數(shù)获搏,由函數(shù)內(nèi)部自己產(chǎn)生一個實例返回
for(var i = 0; i<arr.length; i++){
       arr[i].onclick = Function("alert("+i+");");
}

9)第九種解決方法:使用ES6的let關(guān)鍵字(有些瀏覽器不支持)

"use strict";
var arr = document.getElementsByTagName("p");
for(var i = 0; i<arr.length; i++){
      let j = i;//塊級變量
      arr[i].onclick = function () {
             alert(j);
      }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赖条,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子常熙,更是在濱河造成了極大的恐慌纬乍,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裸卫,死亡現(xiàn)場離奇詭異仿贬,居然都是意外死亡,警方通過查閱死者的電腦和手機墓贿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門茧泪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜓氨,“玉大人,你說我怎么就攤上這事队伟⊙ù担” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵嗜侮,是天一觀的道長港令。 經(jīng)常有香客問我,道長锈颗,這世上最難降的妖魔是什么顷霹? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮宜猜,結(jié)果婚禮上泼返,老公的妹妹穿的比我還像新娘硝逢。我一直安慰自己姨拥,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布渠鸽。 她就那樣靜靜地躺著叫乌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徽缚。 梳的紋絲不亂的頭發(fā)上憨奸,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音凿试,去河邊找鬼排宰。 笑死,一個胖子當(dāng)著我的面吹牛那婉,可吹牛的內(nèi)容都是我干的板甘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼详炬,長吁一口氣:“原來是場噩夢啊……” “哼盐类!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起呛谜,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤在跳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后隐岛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猫妙,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年聚凹,在試婚紗的時候發(fā)現(xiàn)自己被綠了割坠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逻悠。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖韭脊,靈堂內(nèi)的尸體忽然破棺而出童谒,到底是詐尸還是另有隱情,我是刑警寧澤沪羔,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布饥伊,位于F島的核電站,受9級特大地震影響蔫饰,放射性物質(zhì)發(fā)生泄漏琅豆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一篓吁、第九天 我趴在偏房一處隱蔽的房頂上張望茫因。 院中可真熱鬧,春花似錦杖剪、人聲如沸冻押。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洛巢。三九已至,卻和暖如春次兆,著一層夾襖步出監(jiān)牢的瞬間稿茉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工芥炭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留漓库,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓园蝠,卻偏偏與公主長得像渺蒿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子砰琢,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

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

  • 閉包(closure)是Javascript語言的一個難點蘸嘶,也是它的特色,很多高級應(yīng)用都要依靠閉包實現(xiàn)陪汽。 一训唱、變量...
    zock閱讀 1,075評論 2 6
  • 閉包(closure)是Javascript語言的一個難點,也是它的特色挚冤,很多高級應(yīng)用都要依靠閉包實現(xiàn)况增。 一、變量...
    zouCode閱讀 1,271評論 0 13
  • ● 閉包基礎(chǔ) ● 閉包作用 ● 閉包經(jīng)典例子 ● 閉包應(yīng)用 ● 閉包缺點 ● 參考資料 1训挡、閉包基礎(chǔ) 作用域和作...
    lzyuan閱讀 934評論 0 0
  • 自由的感覺 這個軟件不錯
    小黃穿馬甲閱讀 92評論 0 0
  • 在做項目的過程中發(fā)現(xiàn)澳骤,用afn做網(wǎng)絡(luò)請求的時候歧强,經(jīng)常各種英文報錯,導(dǎo)致用戶體驗很差为肮,但是看別人的項目或者以前別人寫...
    YOrange閱讀 1,198評論 0 0