真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

JavaScript精粹基礎(chǔ)進(jìn)階(7)函數(shù)和作用域(閉包、作用域)

轉(zhuǎn)載請注明出處

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、網(wǎng)絡(luò)空間、營銷軟件、網(wǎng)站建設(shè)、吉陽網(wǎng)站維護(hù)、網(wǎng)站推廣。

原文連接http://blog.huanghanlian.com/article/5b698f05b8ea642ea9213f4f

閉包在JavaScript?中是一個(gè)非常重要的概念。

閉包例子
function outer() {
    var loc = 30;
    return loc;
};
console.log(outer()); //30

outer函數(shù)是一個(gè)函數(shù)聲明,有一個(gè)局部變量loc賦值為30,返回loc。

當(dāng)這個(gè)函數(shù)調(diào)用之后,局部變量就會被釋放了,

function outer() {
    var loc = 30;
    return function() {
        return loc;
    };
};
var func = outer();
console.log(func()); //30

這個(gè)outer函數(shù)有一個(gè)loc的局部變量,返回值是一個(gè)匿名函數(shù)表達(dá)式,在這個(gè)函數(shù)表達(dá)式又返回outer函數(shù)的loc局部變量,這種情況loc是不會被釋放掉的。

調(diào)用var func = outer();返回的是一個(gè)匿名函數(shù),這個(gè)匿名函數(shù)里面仍然能夠訪問到outer()de 局部變量loc,當(dāng)outer()函數(shù)被調(diào)用之后,func()這個(gè)函數(shù)再次調(diào)用的時(shí)候任然能訪問到它外層outer()函數(shù)的局部變量loc。
這種情況就是我們通常所說的閉包。

那么閉包的作用是什么呢?在前端編程里,閉包是非常常見的

閉包無處不在




JavaScript 精粹 基礎(chǔ) 進(jìn)階(7)函數(shù)和作用域(閉包、作用域)


比如說我們可能有一些自己的局部變量,或者說我們的函數(shù)有一些外函數(shù)的變量,我們在做點(diǎn)擊事件的時(shí)候,這個(gè)點(diǎn)擊事件可能會用到外層的一些局部變量,有了閉包我們可以在數(shù)據(jù)的傳遞上更為靈活。

! function() {
    var loc = "loc";
    var url = "http://www.huanghanlian.com/";
    $.ajax({
        url: url,
        success: function() {
            //do sth
            console.log(loc);
        }
    });
}();

有一個(gè)異步的請求,用jq的$.ajax方法也可以在success的回調(diào)函數(shù)中去用到外層具體的一些變量。

因?yàn)殚]包的緣故,在最外層匿名函數(shù)調(diào)用結(jié)束后,success的回調(diào)函數(shù)仍然可以訪問外層的局部變量。locurl

閉包-常見錯(cuò)誤之循環(huán)閉包

document.body.innerHTML = "
aa
" + "
bb
" + "
cc
" + "
dd
"; for (var i = 1; i < 4; i++) { document.getElementById("a" + i).addEventListener('click', function() { console.log(i);//始終都是4 }, false); };

這里面在網(wǎng)頁上面添加三個(gè)元素,通過循環(huán)來給這三個(gè)元素綁定事件,想當(dāng)點(diǎn)擊第一個(gè)元素的時(shí)候,輸出1點(diǎn)擊第二個(gè)輸出2第三個(gè)輸出3。實(shí)現(xiàn)方式是先循環(huán)獲取元素,給元素增加點(diǎn)擊事件,點(diǎn)擊事件里面會輸出i的值。

但是上面的代碼始終只會輸出4,這其實(shí)是閉包的原因,addEventListener('click', function() {這里是回調(diào)函數(shù)}是回調(diào)函數(shù),也就是說當(dāng)點(diǎn)擊時(shí)回調(diào)函數(shù)去做你想做的事情, 當(dāng)我點(diǎn)擊的濕乎乎回調(diào)函數(shù)回去動態(tài)的拿到 i的值,這個(gè)i的值在整個(gè)初始化過程中完成之后實(shí)際上i的值就已經(jīng)是4了,所以始終輸出4。

如果想想要實(shí)現(xiàn)效果就要用到閉包

document.body.innerHTML = "
aa
" + "
bb
" + "
cc
"; for (var i = 1; i < 4; i++) { ! function(i) { document.getElementById("a" + i).addEventListener('click', function() { console.log(i);//1,2,3 }, false); }(i); };

這個(gè)例子里面在每一層循環(huán)的時(shí)候,用一個(gè)匿名函數(shù)而且是立即執(zhí)行的匿名函數(shù)給他包裝起來,然后將每一次遍歷的1.2.3分別的值去傳到這個(gè)匿名函數(shù)里,然后匿名函數(shù)接到這個(gè)參數(shù)i再放到點(diǎn)擊事件中去引用i當(dāng)我們每次點(diǎn)擊事件輸出的值i就會取每一個(gè)閉包環(huán)境下的i。所以這樣就能達(dá)到效果。

閉包-封裝

閉包還有個(gè)好處就是可以封裝一些變量

(function() {
    var _userId = 23492;
    var _typeId = 'item';
    var expor = {};

    function converter(userId) {
        return +userId;
    };

    expor.getUserId = function() {
        return converter(_userId);
    };

    expor.getTypeId = function() {
        return _typeId;
    };
    window.expor = expor;
}());
console.log(expor.getUserId()); //23492
console.log(expor.getTypeId()); //item
console.log(expor._userId); //undefined
console.log(expor._typeId); //undefined

比如說以上代碼,有個(gè)立即調(diào)用函數(shù),他有自己的函數(shù)作用域,在里面定義的局部變量外部是不可以訪問到的,最后可以通過window.expor = expor;這樣的方式來去把最終想輸出的對象輸出出去,那么外部就可以通過expor對象上提供的方法,就可以訪問到函數(shù)里面的對象或變量。

閉包的概念

在計(jì)算機(jī)科學(xué)中,閉包(也稱詞法閉包或函數(shù)閉包)是指一個(gè)函數(shù)或函數(shù)的引用,與一個(gè)引用環(huán)境綁在一起。這個(gè)引用環(huán)境是一個(gè)存儲該函數(shù)每個(gè)非局部變量(也叫自由變量)的表。

閉包,不同于一般函數(shù),它允許一個(gè)函數(shù)在立即詞法作用域外調(diào)用時(shí),仍可訪問非本地變量

作用域

全局,函數(shù),eval [作用域]

JavaScript中的作用域,實(shí)際上是比較簡單的。

全局作用域

var a = 10;
console.log(window.a); //10

在最外層聲明變量a,這樣就聲明了全局作用域下的變量a。

for (var i = 0; i < 4; i++) {
    console.log(i); //0.1.2.3
}
console.log(i); //4

在全局范圍內(nèi)用for循環(huán)里面有個(gè)vae i=0定義了一個(gè)變量i,可能會誤解為這個(gè)i只能在這個(gè)for循環(huán)里面可見,對外不可見,實(shí)際上這是錯(cuò)誤的理解,JavaScript中是沒有塊級作用域的,也就是說不管是for循環(huán)while 循環(huán)里面去定義的變量,實(shí)際上和在外面定義的變量,也就是for循環(huán)所在的外面去定義變量實(shí)際上是沒有差別的,所以 i在外面也能訪問到。

函數(shù)作用域

(function() {
    var b = 20;
})();
console.log(b);//test_lt.html:13 Uncaught ReferenceError: b is not defined(…)

上面匿名立即執(zhí)行函數(shù)表達(dá)式,在執(zhí)行的時(shí)候聲明局部變量b,在函數(shù)外面是拿不到的。函數(shù)有自己獨(dú)立的作用域。

eval 作用域

eval("var a=1;");

作用域鏈

var le3 = 3;

function out() {
    var le = 1;

    function out2() {
        var le2 = 2;
        console.log(le, le2, le3); //1 2 3
    }
    out2()
}
out();

out()函數(shù)中有一個(gè)內(nèi)部函數(shù)out2()它里面有一個(gè)局部變量le2,函數(shù)out2()能訪問到自己的內(nèi)部變量le2,也可以在向上訪問le變量,也就是所謂的閉包,可以訪問外層函數(shù)的局部變量,對于函數(shù)out2()來講也叫作它的自由變量,還可以訪問最外層的le3變量,也就是全局對象,這個(gè)作用域手機(jī)從內(nèi)向外都可以訪問的。

function out() {
    var le = 1;
    var func = new Function("var p=0;console.log(p);console.log(le)");
    func();
}
out();
//輸出
//0
//Uncaught ReferenceError: le is not defined(…)

如果使用new Function去構(gòu)造的一個(gè)函數(shù),構(gòu)造器,去調(diào)用構(gòu)造器定義位置所在的變量le的。

利用函數(shù)作用域封裝

(function() {
    //do sth here
    var a, b;
})();

! function() {
    //do sth here
    var a, b;
}();

利用函數(shù)作用域的特性,我們經(jīng)??吹胶芏囝悗?,或者代碼最外層如果沒有模塊化的一些工具的話,會在最外層去寫一個(gè)function這樣一個(gè)匿名函數(shù),這樣的好處就是可以把函數(shù)內(nèi)部的變量變成函數(shù)的局部變量,而不是全局變量,這樣防止大量的全局變量和其他的一些類庫或者其他代碼引發(fā)沖突,! function() {}()這樣的作用其實(shí)就是把函數(shù)變成函數(shù)表達(dá)式,而不是函數(shù)聲明,如果省略掉這個(gè)!嘆號的話,那么他會理解為函數(shù)聲明,會被前置處理掉,那么最后留下一個(gè)括號或者你省略名字的話,都會報(bào)語法錯(cuò)誤。


分享標(biāo)題:JavaScript精粹基礎(chǔ)進(jìn)階(7)函數(shù)和作用域(閉包、作用域)
網(wǎng)站URL:http://weahome.cn/article/gcjhij.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部