国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS 閉包

sihai / 1732人閱讀

摘要:你可能經(jīng)常看到這句話創(chuàng)建閉包的最常見的方式就是在一個(gè)函數(shù)內(nèi)創(chuàng)建另一個(gè)函數(shù),通過另一個(gè)函數(shù)訪問這個(gè)函數(shù)的局部變量。這種現(xiàn)象稱之為閉包。雖然中沒有類這樣的機(jī)制,但是通過使用閉包,我們可以模擬出這樣的機(jī)制。

JS 閉包

JS編程的時(shí)候你一定遇到過這個(gè)問題:局部變量實(shí)現(xiàn)累加,看下面例子:

function aotuadd(){
    var a=1;
    a++;
    console.log(a);
}
aotuadd();//2
autuadd();//2

上面的代碼無法實(shí)現(xiàn)累加,這時(shí)可能有的人就會(huì)選擇把a(bǔ)放在全局作用域中,能實(shí)現(xiàn)累加功能,但是會(huì)使全局變量增多,這是我們不想看到的。
其實(shí)之所以把a(bǔ)放在全局作用域中,是因?yàn)閍utoadd函數(shù)的作用域被全局作用域包裹,所以我們可以在全局作用域中取值;
那么我們是不是可以給autoadd外層再包裹一個(gè)作用域(假設(shè)是wapper),然后將這個(gè)a放在wapper作用域中,問題不就解決了嘛。
我們既能訪問wrapper中的a,又不必增加全局變量。因?yàn)閖s中只有函數(shù)能夠產(chǎn)生作用域,所以其實(shí)就是再aotoadd外包裹一個(gè)wrapper函數(shù),試著寫一下:

function wrapper(){
    var a=1;
    function autoadd(){
        a++;
        console.log(a);
    }
}
wrapper();

寫到這里發(fā)現(xiàn),我們無法訪問autoadd,怎么解決:

function wrapper(){
    var a=1;
    function autoadd(){
        a++;
        console.log(a);
    }
    window.bar=autoadd;
}
wrapper()
bar();//2
bar();//3

上面這種方法是能夠解決無法調(diào)用的問題的,但是這回到了我們最開始遇到的問題,增加了全局變量/函數(shù),這是我們不想看到的;另一種解決方法:

function wrapper(){
    var a=1;
    function autoadd(){//必要條件
        a++;//必要條件
        console.log(a);
    }
    return autoadd;
}
var x=wrapper()//返回一個(gè)函數(shù),巧合的是,返回的這個(gè)函數(shù)體中,還有一個(gè)變量a要引用wrapper作用域下的a,所以這個(gè)a不能銷毀,wrapper()上下文環(huán)境不被銷毀,依然存在于執(zhí)行上下文棧中;
x();
x();

通過返回函數(shù)的方法進(jìn)行調(diào)用,上面的這種寫法就是我們最常見的閉包的寫法,也就是說,閉包的產(chǎn)生,其實(shí)并不是一定依賴于“返回函數(shù)”這個(gè)條件,只不過不通過這種方法調(diào)用有違初衷;

看懂了上面這個(gè)例子,閉包的概念也呼之欲出:閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù),即當(dāng)前作用域總能訪問外部作用域中的變量。
你可能經(jīng)常看到這句話:“創(chuàng)建閉包的最常見的方式就是在一個(gè)函數(shù)內(nèi)創(chuàng)建另一個(gè)函數(shù),通過另一個(gè)函數(shù)訪問這個(gè)函數(shù)的局部變量”。其實(shí)我覺得恰恰就是這句話,導(dǎo)致很多人無法理解閉包,換成下面這種說法更好理解:創(chuàng)建閉包的最常見的方式是在一個(gè)函數(shù)外部包裹另一個(gè)函數(shù),通過在另一個(gè)函數(shù)內(nèi)部定義變量的方式,使我們想要的變量駐留在外層函數(shù)中,減少全局變量。

閉包的兩個(gè)必要條件:函數(shù)外層有函數(shù)/ 內(nèi)層函數(shù)要使用外層函數(shù)中的變量

我們總結(jié)一下,上面var x=wrapper()和function warpper()可以利用立即執(zhí)行函數(shù)合寫,進(jìn)一步減少全局變量:

var x=(function(){
        var a=1;
        return function(){
            a++;
            console.log(a);
        }
})();
x();//2
x();//3
x=null;//解除引用,等待垃圾回收

或者:

function Myobj(){
    var age=1;;
    this.autoadd=function(){
        age++;
        console.log(age);
        //return age;
    }
}
var obj=new Myobj();
obj.autoadd();
obj.autoadd();

另一個(gè)常見問題:
for循環(huán)給網(wǎng)頁中一連串元素綁定,例如onclick事件:

var fn = function() {
        var divs = document.querySelectorAll("div");
        for (var i = 0; i < 3; i++) {
                divs[i].onclick = function() {
                        alert(i);
                };
        }
};
fn();

點(diǎn)擊每個(gè)div都會(huì)彈出3。這是為什么呢?
我們先來分析一下原因:onclick事件是一個(gè)異步回調(diào)函數(shù)的指針,并不會(huì)立即執(zhí)行,上面的函數(shù)表達(dá)式,并不會(huì)進(jìn)行變量賦值。只有在調(diào)用一個(gè)函數(shù)時(shí),一個(gè)新的執(zhí)行上下文才會(huì)被創(chuàng)建出來。那么我們是不是可以通過調(diào)用函數(shù)的方法,來創(chuàng)建多個(gè)新的執(zhí)行上下文環(huán)境,創(chuàng)建新的作用域,這樣不同的調(diào)用就可以有不同的參數(shù)。那么解決思路也是外層包裹function的方法,即利用閉包:

var fn = function() {
        var divs = document.querySelectorAll("div");
        for (var i = 0; i < 3; i++) {
                divs[i].onclick = (function(a) {//立即執(zhí)行函數(shù),創(chuàng)建新的執(zhí)行上下文
                        alert(a);
                })(i);
        }
};
fn();

或者:

var fn = function() {
        var divs = document.querySelectorAll("div");
        for (var i = 0; i < 3; i++) {
                (function(i){//立即執(zhí)行函數(shù),創(chuàng)建新的執(zhí)行上下文,將i駐留在內(nèi)存中
                    divs[i].onclick = function() {
                        alert(i);
                })(i);
        }
};
fn();

另一種解決方法:(利用事件代理)

var ul=document.querySelector("ul");
var lis=ul.querySelectorAll("ul li");
ul.addEventListener("click", function (e) {
    var target= e.target;
    if(target.nodeName.toUpperCase()==="LI"){
        alert([].indexOf.call(lis,target));
    }
},false)

理解閉包的關(guān)鍵就是下面這句:
閉包:當(dāng)一個(gè)函數(shù)在定義它的作用域以外的地方被調(diào)用時(shí),它訪問的依然是定義它時(shí)的作用域。這種現(xiàn)象稱之為閉包。
JavaScript中的函數(shù)運(yùn)行在它們被定義的作用域里,而不是它們被執(zhí)行的作用域里。——《JavaScript語言精粹》

閉包的優(yōu)點(diǎn):
1)使變量駐留在內(nèi)存中(多了變?nèi)秉c(diǎn));
2)避免全局變量污染;
3)私有化變量;
閉包的缺點(diǎn):
1)因?yàn)殚]包會(huì)攜帶包含它的函數(shù)的作用域,所以比其他函數(shù)占用更多內(nèi)存;
2)使用不當(dāng)會(huì)造成內(nèi)存泄漏;

閉包應(yīng)用場景(來自《javascript高級(jí)程序設(shè)計(jì)》)
1.使用閉包可以在JS中模擬塊級(jí)作用域(ECMAScript6標(biāo)準(zhǔn)之前的JavaScript本身沒有塊級(jí)作用域的概念);

function outputNumbers(count){
      (function(){
               for(var i = 0; i < count; i++){
               alert(i);
               }
      })();
  alert(i); //導(dǎo)致一個(gè)錯(cuò)誤!
}

2.閉包可以用于在對(duì)象中創(chuàng)建私有變量;

// 1.2.閉包可以用于在對(duì)象中創(chuàng)建私有變量

  function MyObject(){
    // 私有變量和私有函數(shù)
    var privateVariable = 10;
    function privateFunction(){
      return false;
    }
    // 特權(quán)方法,調(diào)用私有方法、函數(shù)
    this.publicMethod = function(){
      privateVariable++;
      return privateFunction();
    }
  }

閉包的運(yùn)用
1.匿名自執(zhí)行函數(shù)
我們?cè)趯?shí)際情況下經(jīng)常遇到這樣一種情況,即有的函數(shù)只需要執(zhí)行一次,其內(nèi)部變量無需維護(hù),比如UI的初始化,那么我們可以使用閉包:

//將全部li字體變?yōu)榧t色
(function(){    
    var els = document.getElementsByTagName("li");
    for(var i = 0,lng = els.length;i < lng;i++){
        els[i].style.color = "red";
    }    
})();  

我們創(chuàng)建了一個(gè)匿名的函數(shù),并立即執(zhí)行它,由于外部無法引用它內(nèi)部的變量,
因此els,i,lng這些局部變量在執(zhí)行完后很快就會(huì)被釋放,節(jié)省內(nèi)存!
關(guān)鍵是這種機(jī)制不會(huì)污染全局對(duì)象。
2. 實(shí)現(xiàn)封裝/模塊化代碼

var person= function(){    
    //變量作用域?yàn)楹瘮?shù)內(nèi)部,外部無法訪問    
    var name = "default";       
return {    
       getName : function(){    
           return name;    
       },    
       setName : function(newName){    
           name = newName;    
       }    
    }    
}();
console.log(person.name);//直接訪問,結(jié)果為undefined    
console.log(person.getName());  //default 
person.setName("jozo");    
console.log(person.getName());  //jozo

3. 實(shí)現(xiàn)面向?qū)ο笾械膶?duì)象
這樣不同的對(duì)象(類的實(shí)例)擁有獨(dú)立的成員及狀態(tài),互不干涉。雖然JavaScript中沒有類這樣的機(jī)制,但是通過使用閉包,
我們可以模擬出這樣的機(jī)制。還是以上邊的例子來講:

function Person(){    
    var name = "default";       
return {    
       getName : function(){    
           return name;    
       },    
       setName : function(newName){    
           name = newName;    
       }    
    }    
};    
var person1= Person();    
print(person1.getName());    
john.setName("person1");    
print(person1.getName());  // person1  
var person2= Person();    
print(person2.getName());    
jack.setName("erson2");    
print(erson2.getName());  //person2

Person的兩個(gè)實(shí)例person1 和 person2 互不干擾!因?yàn)檫@兩個(gè)實(shí)例對(duì)name這個(gè)成員的訪問是獨(dú)立的 。

初學(xué)js很多理解不到位的地方,望批評(píng)指正!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/92541.html

相關(guān)文章

  • JS 中的閉包是什么?

    摘要:大名鼎鼎的閉包面試必問。閉包的作用是什么。看到閉包在哪了嗎閉包到底是什么五年前,我也被這個(gè)問題困擾,于是去搜了并總結(jié)下來。關(guān)于閉包的謠言閉包會(huì)造成內(nèi)存泄露錯(cuò)。閉包里面的變量明明就是我們需要的變量,憑什么說是內(nèi)存泄露這個(gè)謠言是如何來的因?yàn)椤? 本文為饑人谷講師方方原創(chuàng)文章,首發(fā)于 前端學(xué)習(xí)指南。 大名鼎鼎的閉包!面試必問。請(qǐng)用自己的話簡述 什么是「閉包」。 「閉包」的作用是什么。 首先...

    Enlightenment 評(píng)論0 收藏0
  • js閉包的本質(zhì)

    摘要:也正因?yàn)檫@個(gè)閉包的特性,閉包函數(shù)可以讓父函數(shù)的數(shù)據(jù)一直駐留在內(nèi)存中保存,從而這也是后來模塊化的基礎(chǔ)。只有閉包函數(shù),可以讓它的父函數(shù)作用域永恒,像全局作用域,一直在內(nèi)存中存在。的本質(zhì)就是如此,每個(gè)模塊文件就是一個(gè)大閉包。 為什么會(huì)有閉包 js之所以會(huì)有閉包,是因?yàn)閖s不同于其他規(guī)范的語言,js允許一個(gè)函數(shù)中再嵌套子函數(shù),正是因?yàn)檫@種允許函數(shù)嵌套,導(dǎo)致js出現(xiàn)了所謂閉包。 function...

    qianfeng 評(píng)論0 收藏0
  • 談?wù)勎宜斫獾?em>閉包,js、php、golang里的closure

    摘要:當(dāng)初看這個(gè)解釋有點(diǎn)懵逼,理解成閉包就是函數(shù)中的函數(shù)了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學(xué)習(xí)語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數(shù)作為值返回的情況,被返回的函數(shù)引用了生成它的母函數(shù)中的變量。 本人開始接觸編程是從js開始的,當(dāng)時(shí)網(wǎng)上很多人說閉包是難點(diǎn),各種地方對(duì)閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發(fā)現(xiàn)不光是js,php、...

    betacat 評(píng)論0 收藏0
  • 談?wù)勎宜斫獾?em>閉包,js、php、golang里的closure

    摘要:當(dāng)初看這個(gè)解釋有點(diǎn)懵逼,理解成閉包就是函數(shù)中的函數(shù)了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學(xué)習(xí)語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數(shù)作為值返回的情況,被返回的函數(shù)引用了生成它的母函數(shù)中的變量。 本人開始接觸編程是從js開始的,當(dāng)時(shí)網(wǎng)上很多人說閉包是難點(diǎn),各種地方對(duì)閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發(fā)現(xiàn)不光是js,php、...

    zhoutao 評(píng)論0 收藏0
  • 詳解js閉包

    摘要:但閉包的情況不同嵌套函數(shù)的閉包執(zhí)行后,,然后還在被回收閉包會(huì)使變量始終保存在內(nèi)存中,如果不當(dāng)使用會(huì)增大內(nèi)存消耗。每個(gè)函數(shù),不論多深,都可以認(rèn)為是全局的子作用域,可以理解為閉包。 閉包(closure)是Javascript語言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)。 閉包的特性 閉包有三個(gè)特性: 1.函數(shù)嵌套函數(shù) 2.函數(shù)內(nèi)部可以引用外部的參數(shù)和變量 3.參數(shù)和變量不會(huì)...

    Chiclaim 評(píng)論0 收藏0
  • JS腳丫系列】重溫閉包

    摘要:內(nèi)部的稱為內(nèi)部函數(shù)或閉包函數(shù)。過度使用閉包會(huì)導(dǎo)致性能下降。,閉包函數(shù)分為定義時(shí),和運(yùn)行時(shí)。循環(huán)會(huì)先運(yùn)行完畢,此時(shí),閉包函數(shù)并沒有運(yùn)行。閉包只能取得外部函數(shù)中的最后一個(gè)值。事件綁定種的匿名函數(shù)也是閉包函數(shù)。而對(duì)象中的閉包函數(shù),指向。 閉包概念解釋: 閉包(也叫詞法閉包或者函數(shù)閉包)。 在一個(gè)函數(shù)parent內(nèi)聲明另一個(gè)函數(shù)child,形成了嵌套。函數(shù)child使用了函數(shù)parent的參數(shù)...

    MartinDai 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<