好程式設計師技術分析JavaScript閉包特性詳解
好程式設計師 技術分析 JavaScript 閉包特性詳解 , 今天來總結一下 js 閉包 的那些事,以及遇到的坑和解決方法,希望對你有所幫助。
是的,沒看錯標題,重要的事情要說三篇, JavaScript 閉包。
首先先簡要總結閉包特性:
· 函式的區域性變數在函式返回之後仍然可用
· 棧上的記憶體空間在函式返回之後仍在存在,不被回收
給個例子。下面這段程式碼會返回一個函式的引用:
function sayHello2(name) {
var text = 'Hello ' + name; // Local variable
var sayAlert = function() { alert(text); }
return sayAlert;
}
say2 = sayHello2('Bob');
say2(); // alerts "Hello Bob"
對於這段程式碼, C 程式設計師可能會認為 sayAlert 和 say2 一樣,都是指向一個函式的指標。但實際上它倆有一個重要區別: 在 JavaScript 中,你可以認為一個函式的指標變數同時擁有兩個指標。一個指向這個函式,另一個隱藏的指標指向一個閉包。
重點在於你的函式內是否引用的外部變數。
在 JavaScript 中,如果你在一個函式內定義一個新的函式,那麼這個新的函式就是一個閉包。 對於 C 或者其他高階語言,函式執行結束並返回之後,它所佔用的棧空間將被釋放回收。函式內定義的區域性變數將不再可用。但在 JavaScript 中,並不這樣。如上所示,函式執行結束後,它所佔用的棧空間並不會被全部回收。
上面是基本理論。更進一步,再來一個例子:
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
這個例子說明:閉包中使用的函式區域性變數並非是值複製,而是引用。 say667() 執行結束之後 number 所在的那塊記憶體的值為 667 ,而 sayNumber() 是在 say667() 執行結束之後才執行,當它訪問 number 所在的記憶體時,結果自然也是 667 。
再進一步,看看用 closure 時易發生的錯誤的例子:
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]();
}
}
時刻保持清醒:變數是在記憶體裡的,閉包使用的是記憶體的引用而不是那塊記憶體的值複製。
當你在迴圈中定義函式(閉包)的時候得小心,它可能並不像你最開始想的那樣工作。關鍵有兩個:
· 子函式使用的是外部函式的區域性變數的引用。
· 迴圈內只是 定義 了子函式,並沒有 執行 這個字函式。
最後,來一個最抽象的例子:
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;
這個例子說明,閉包的建立時機是在函式被呼叫的時候。每次函式呼叫都會生成一個新的閉包,也就是一塊新的記憶體區域。因為函式每次呼叫都會新分配一塊棧記憶體,這是一回事。
最後我自己來總結一下閉包:
· 函式的區域性變數在其他地方被引用
· 閉包有兩種基本情況:閉包的返回值是一個函式,它其中使用了該閉包的區域性變數;閉包內定義了內部函式,內部函式引用了閉包的區域性變數
· 每次函式呼叫,都會生成一個新的閉包,分配新的記憶體
例項:(滑過 tab )
window.onload= function(){
var tits = $('#tabTit1 li');
var cons = $('#tabCon1 .con');
var len = cons.length;
var liChange = function(){
for(var n=0;n<len;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.length; i++){
tits[i].i = i;
tits[i].onmouseover = function(){
liChange();
cons[this.i].addClass('cur');
tits[this.i].addClass('cur');
}
}
};
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2640399/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 好程式設計師技術分享淺談JavaScript中的閉包程式設計師JavaScript
- 好程式設計師HTML5培訓技術分享JavaScript 閉包程式設計師HTMLJavaScript
- 好程式設計師技術文件HTML5開發中的javascript閉包程式設計師HTMLJavaScript
- 好程式設計師前端教程之JavaScript閉包和匿名函式的關係詳解程式設計師前端JavaScript函式
- 好程式設計師技術教程分享JavaScript運動框架程式設計師JavaScript框架
- JavaScript閉包詳解JavaScript
- 好程式設計師web前端教程分享js閉包程式設計師Web前端JS
- 好程式設計師分享JavaScript六種繼承方式詳解程式設計師JavaScript繼承
- 好程式設計師web前端教程分享前端javascript練習題之閉包案例程式設計師Web前端JavaScript
- Javascript—閉包詳解(3)JavaScript
- 好程式設計師web前端教程之詳解JavaScript嚴格模式程式設計師Web前端JavaScript模式
- 好程式設計師技術分享html5和JavaScript的區別程式設計師HTMLJavaScript
- 好程式設計師Java培訓Java程式設計師必學技術程式設計師Java
- 好程式設計師web前端培訓分享JavaScript學習筆記閉包與繼承程式設計師Web前端JavaScript筆記繼承
- 好程式設計師分享JavaScript名稱空間模式例項詳解程式設計師JavaScript模式
- 好程式設計師大資料教程分享Scala系列之閉包程式設計師大資料
- 好程式設計師分享placeholder屬性詳解程式設計師
- javascript中的閉包closure詳解JavaScript
- 好程式設計師分享JavaScript事件委託代理和函式封裝詳解程式設計師JavaScript事件函式封裝
- 好程式設計師web前端技術分享css盒模型程式設計師Web前端CSS模型
- 程式設計師如何寫好一篇技術文章?程式設計師
- 好程式設計師分享HTML5精品技術文章--前端崗位需求分析程式設計師HTML前端
- 好程式設計師Python培訓之詳解eval好與壞程式設計師Python
- 好程式設計師Java培訓分享For迴圈詳解程式設計師Java
- 好程式設計師前端學習路線分享模擬JavaScript中物件導向技術程式設計師前端JavaScript物件
- 程式設計師寫好技術文章的幾點小技巧程式設計師
- 好程式設計師Java培訓分享Java之反射技術程式設計師Java反射
- 好程式設計師web前端技術分享媒體查詢程式設計師Web前端
- 好程式設計師分享Css詳解bem書寫規範程式設計師CSS
- 好程式設計師Python培訓分享For迴圈用法詳解程式設計師Python
- 好程式設計師分享JavaScript建立物件的方式!程式設計師JavaScript物件
- 好程式設計師技術解析Hadoop和spark的效能比較程式設計師HadoopSpark
- 好程式設計師web前端技術之CSS3過渡程式設計師Web前端CSSS3
- 好程式設計師web前端培訓分享詳解JavaScript學習筆記建構函式程式設計師Web前端JavaScript筆記函式
- 好程式設計師雲端計算教程分享Mysql技術知識點程式設計師MySql
- 好程式設計師Java學習路線分享finalize()方法詳解程式設計師Java
- 好程式設計師web前端學習路線分享Jsonp詳解程式設計師Web前端JSON
- 好程式設計師Java教程Java動態代理機制詳解程式設計師Java