這篇文章主要介紹“分析JavaScript閉包特性”,在日常操作中,相信很多人在分析JavaScript閉包特性問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”分析JavaScript閉包特性”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
成都創(chuàng)新互聯(lián)公司長期為上千多家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為黃石港企業(yè)提供專業(yè)的網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè),黃石港網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
首先先簡要總結(jié)閉包特性:
· 函數(shù)的局部變量在函數(shù)返回之后仍然可用
· 棧上的內(nèi)存空間在函數(shù)返回之后仍在存在,不被回收
給個例子。下面這段代碼會返回一個函數(shù)的引用:
function sayHello2(name) {
var text = 'Hello ' + name; // Local variable
var sayAlert = function() { alert(text); }
return sayAlert;
}
say2 = sayHello2('Bob');
say2(); // alerts "Hello Bob"
對于這段代碼,C程序員可能會認(rèn)為sayAlert和say2一樣,都是指向一個函數(shù)的指針。但實(shí)際上它倆有一個重要區(qū)別: 在JavaScript中,你可以認(rèn)為一個函數(shù)的指針變量同時擁有兩個指針。一個指向這個函數(shù),另一個隱藏的指針指向一個閉包。
重點(diǎn)在于你的函數(shù)內(nèi)是否引用的外部變量。
在JavaScript中,如果你在一個函數(shù)內(nèi)定義一個新的函數(shù),那么這個新的函數(shù)就是一個閉包。 對于C或者其他高級語言,函數(shù)執(zhí)行結(jié)束并返回之后,它所占用的??臻g將被釋放回收。函數(shù)內(nèi)定義的局部變量將不再可用。但在JavaScript中,并不這樣。如上所示,函數(shù)執(zhí)行結(jié)束后,它所占用的棧空間并不會被全部回收。
上面是基本理論。更進(jìn)一步,再來一個例子:
function say667() {
// Local variable that ends up within closure
var num = 666;
var sayAlert = function() { alert(num); }
num++;
return sayAlert;
}
var sayNumber = say667();
sayNumber(); // alerts 667
這個例子說明:閉包中使用的函數(shù)局部變量并非是值拷貝,而是引用。say667()執(zhí)行結(jié)束之后number所在的那塊內(nèi)存的值為667,而sayNumber()是在say667()執(zhí)行結(jié)束之后才執(zhí)行,當(dāng)它訪問number所在的內(nèi)存時,結(jié)果自然也是667。
再進(jìn)一步,看看用closure時易發(fā)生的錯誤的例子:
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push( function() {alert(item + ' ' + list[i])} );
}
return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
// Using j only to help prevent confusion -- could use i.
for (var j = 0; j < fnlist.length; j++) {
fnlist[j]();
}
}
時刻保持清醒:變量是在內(nèi)存里的,閉包使用的是內(nèi)存的引用而不是那塊內(nèi)存的值拷貝。
當(dāng)你在循環(huán)中定義函數(shù)(閉包)的時候得小心,它可能并不像你最開始想的那樣工作。關(guān)鍵有兩個:
· 子函數(shù)使用的是外部函數(shù)的局部變量的引用。
· 循環(huán)內(nèi)只是定義了子函數(shù),并沒有執(zhí)行這個字函數(shù)。
最后,來一個最抽象的例子:
function newClosure(someNum, someRef) {
// Local variables that end up within closure
var num = someNum;
var anArray = [1,2,3];
var ref = someRef;
return function(x) {
num += x;
anArray.push(num);
alert('num: ' + num +
'\nanArray ' + anArray.toString() +
'\nref.someVar ' + ref.someVar);
}
}
obj = {someVar: 4};
fn1 = newClosure(4, obj);
fn2 = newClosure(5, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;
這個例子說明,閉包的創(chuàng)建時機(jī)是在函數(shù)被調(diào)用的時候。每次函數(shù)調(diào)用都會生成一個新的閉包,也就是一塊新的內(nèi)存區(qū)域。因?yàn)楹瘮?shù)每次調(diào)用都會新分配一塊棧內(nèi)存,這是一回事。
最后我自己來總結(jié)一下閉包:
· 函數(shù)的局部變量在其他地方被引用
· 閉包有兩種基本情況:閉包的返回值是一個函數(shù),它其中使用了該閉包的局部變量;閉包內(nèi)定義了內(nèi)部函數(shù),內(nèi)部函數(shù)引用了閉包的局部變量
· 每次函數(shù)調(diào)用,都會生成一個新的閉包,分配新的內(nèi)存
實(shí)例:(滑過tab)
window.onload= function(){
var tits = $('#tabTit1 li');
var cons = $('#tabCon1 .con');
var len = cons.length;
var liChange = function(){
for(var n=0;n tits[n].className = tits[n].className.replace(/\s*cur/g,''); cons[n].className = cons[n].className.replace(/\s*cur/g,''); } } for(var i = 0; i tits[i].i = i; tits[i].onmouseover = function(){ liChange(); cons[this.i].addClass('cur'); tits[this.i].addClass('cur'); } } }; 到此,關(guān)于“分析JavaScript閉包特性”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
本文題目:分析JavaScript閉包特性
URL鏈接:http://weahome.cn/article/gdscpg.html