亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

理解和運用JavaScript的閉包機制

 更新時間:2015年08月13日 12:14:24   作者:libuchao  
這篇文章主要介紹了理解和運用JavaScript的閉包機制,是JavaScript入門學習中的基礎知識,需要的朋友可以參考下

偉大的愛因斯坦同志說過:“如果你無法向一個 6 歲小孩解釋清楚某問題,那說明你自己都沒整明白”。然而,當我向一個 27 歲的朋友解釋什么是閉包時,卻徹底失敗了。

這原本是國外某哥們兒在 Stack Overflow 上對 JavaScript 閉包所提出的問題。不過既然此問題是在 Stack Overflow 提出的,當然也會有很多高手出來解答,其中有些回答確實是經典,如下面這個:

如果在一個外部函數(shù)中再定義一個內部函數(shù),即函數(shù)嵌套函數(shù),那么內部函數(shù)也可以訪問外部函數(shù)中的變量:

function foo(x) {
 var tmp = 3;
 function bar(y) {
 alert(x + y + (++tmp));
 }
 bar(10);
}

foo(2); // alert 16
foo(2); // alert 16
foo(2); // alert 16

此段代碼可以正確執(zhí)行,并返回結果:16,因為 bar 能訪問外部函數(shù)的變量 tmp, 同時也能訪問外部函數(shù) foo 的參數(shù) x。但以上示例不是閉包!

要實現(xiàn)閉包的話,需要將內部函數(shù)作為外部函數(shù)的返回值返回,內部函數(shù)在返回前,會將所有已訪問過的外部函數(shù)中的變量在內存中鎖定,也就是說,這些變量將常駐 bar 的內存中,不會被垃圾回收器回收,如下:

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + (++tmp));
 }
}
var bar = foo(2); // bar 現(xiàn)在是個閉包了
bar(10); // alert 16
bar(10); // alert 17
bar(10); // alert 18

上述代碼中,第一次執(zhí)行 bar 時,仍會返回結果:16,因為 bar 仍然可以訪問 x 及 tmp,盡管它已經不直接存在于 foo 的作用域內。那么既然 tmp 被鎖定在 bar 的閉包里,那么每次執(zhí)行 bar 的時候,tmp 都會自增一次,所以第二次和第三次執(zhí)行 bar 時,分別返回 17 和 18。

此示例中,x 僅僅是個純粹的數(shù)值,當 foo 被調用時,數(shù)值 x 就會作為參數(shù)被拷貝至 foo 內。

但是 JavaScript 處理對象的時候,使用的總是引用,如果用一個對象作為參數(shù)來調用 foo,那么 foo 中傳入的實際上是原始對象的引用,所以這個原始對象也相當于被閉包了,如下:

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + tmp++);
 x.memb = x.memb ? x.memb + 1 : 1;
 alert(x.memb);
 }
}
var age = new Number(2);
var bar = foo(age); // bar 現(xiàn)在是個閉包了
bar(10); // alert 15 1
bar(10); // alert 16 2
bar(10); // alert 17 3

和期望的一樣,每次執(zhí)行 bar(10) 時,不但 tmp 自增了,x.memb 也自增了,因為函數(shù)體內的 x 和函數(shù)體外的 age 引用的是同一個對象。

via http://stackoverflow.com/questions/111102/how-do-javascript-closures-work

補充:通過以上示例,應該能比較清楚的理解閉包了。如果覺得自己理解了,可以試著猜猜下面這段代碼的執(zhí)行結果:

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + tmp++);
 x.memb = x.memb ? x.memb + 1 : 1;
 alert(x.memb);
 }
}
var age = new Number(2);
var bar1 = foo(age); // bar1 現(xiàn)在是個閉包了
bar1(10); // alert 15 1
bar1(10); // alert 16 2
bar1(10); // alert 17 3

var bar2 = foo(age); // bar2 現(xiàn)在也是個閉包了
bar2(10); // alert ? ?
bar2(10); // alert ? ?
bar2(10); // alert ? ?

bar1(10); // alert ? ?
bar1(10); // alert ? ?
bar1(10); // alert ? ?

實際使用的時候,閉包可以創(chuàng)建出非常優(yōu)雅的設計,允許對funarg上定義的多種計算方式進行定制。如下就是數(shù)組排序的例子,它接受一個排序條件函數(shù)作為參數(shù):

[1, 2, 3].sort(function (a, b) {
 ... // 排序條件
});

同樣的例子還有,數(shù)組的map方法是根據函數(shù)中定義的條件將原數(shù)組映射到一個新的數(shù)組中:

[1, 2, 3].map(function (element) {
 return element * 2;
}); // [2, 4, 6]

使用函數(shù)式參數(shù),可以很方便的實現(xiàn)一個搜索方法,并且可以支持無限制的搜索條件:

someCollection.find(function (element) {
 return element.someProperty == 'searchCondition';
});

還有應用函數(shù),比如常見的forEach方法,將函數(shù)應用到每個數(shù)組元素:

[1, 2, 3].forEach(function (element) {
 if (element % 2 != 0) {
  alert(element);
 }
}); // 1, 3

順便提下,函數(shù)對象的 apply 和 call方法,在函數(shù)式編程中也可以用作應用函數(shù)。 這里,我們將它們看作是應用函數(shù) —— 應用到參數(shù)中的函數(shù)(在apply中是參數(shù)列表,在call中是獨立的參數(shù)):

(function () {
 alert([].join.call(arguments, ';')); // 1;2;3
}).apply(this, [1, 2, 3]);

閉包還有另外一個非常重要的應用 —— 延遲調用:

var a = 10;
setTimeout(function () {
 alert(a); // 10, after one second
}, 1000);
還有回調函數(shù):

//...
var x = 10;
// only for example
xmlHttpRequestObject.onreadystatechange = function () {
 // 當數(shù)據就緒的時候,才會調用;
 // 這里,不論是在哪個上下文中創(chuàng)建
 // 此時變量“x”的值已經存在了
 alert(x); // 10
};
//...

還可以創(chuàng)建封裝的作用域來隱藏輔助對象:

var foo = {};

// 初始化
(function (object) {

 var x = 10;

 object.getX = function _getX() {
  return x;
 };

})(foo);

alert(foo.getX()); // 獲得閉包 "x" – 10

相關文章

  • JavaScript操作DOM對象詳解

    JavaScript操作DOM對象詳解

    本文詳細講解了JavaScript操作DOM對象的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • JavaScript中使用自然對數(shù)ln的方法

    JavaScript中使用自然對數(shù)ln的方法

    這篇文章主要介紹了JavaScript中使用自然對數(shù)ln的方法,是JS入門學習中的基礎知識,需要的朋友可以參考下
    2015-06-06
  • 淺談Javascript中深復制

    淺談Javascript中深復制

    本文主要給大家介紹了javascript中深復制的實現(xiàn)方式,這里推薦給有需要的小伙伴參考下。
    2014-12-12
  • Javascript基礎教程之數(shù)據類型 (字符串 String)

    Javascript基礎教程之數(shù)據類型 (字符串 String)

    javascript一共有9種數(shù)據類型,分別是字符串 String、數(shù)值型 Number、布爾型 Boolean、未定義 Undefine、空值 Null、對象 Object、引用Refernce、列表型 List、完成型 Completion,我們今天首先來看看(字符串 String)
    2015-01-01
  • 深入理解JavaScript系列(21):S.O.L.I.D五大原則之接口隔離原則ISP詳解

    深入理解JavaScript系列(21):S.O.L.I.D五大原則之接口隔離原則ISP詳解

    這篇文章主要介紹了深入理解JavaScript系列(21):S.O.L.I.D五大原則之接口隔離原則ISP詳解,本文講解了JavaScript接口、ISP與JavaScript、墮落的實現(xiàn)、靜態(tài)耦合、語義耦合、可擴展性等內容,需要的朋友可以參考下
    2015-03-03
  • JavaScript高級程序設計(第3版)學習筆記10 再訪js對象

    JavaScript高級程序設計(第3版)學習筆記10 再訪js對象

    在ECMAScript中,兩個核心主題就是對象與函數(shù),而這兩個主題也有些互相纏繞的,在前面幾個博文中大略的過了一遍函數(shù)相關的基礎知識,這篇文章再回到對象主題上來
    2012-10-10
  • 了解javascript中的Dom操作

    了解javascript中的Dom操作

    DOM 給我們提供了一些方法,讓我們可以使用js來控制頁面中的標簽等。下面小編和大家來一起學習下吧
    2019-05-05
  • javascript異步編程的4種方法

    javascript異步編程的4種方法

    本文總結了"異步模式"編程的4種方法,理解它們可以讓你寫出結構更合理、性能更出色、維護更方便的Javascript程序
    2014-02-02
  • 如何學習Javascript入門指導

    如何學習Javascript入門指導

    首先要說明的是,咱現(xiàn)在不是高手,最多還是一個半桶水,算是入了JS的門
    2013-11-11
  • 關于JavaScript中string 的replace

    關于JavaScript中string 的replace

    在使用JavaScript對字符串進行處理的時候我們經常會用到replace方法,很簡單的一個方法,以前一直不以為意,直到今天看JavaScript語言精粹的時候讀到了一個有趣的小例子的時候,并不是十分理解,了解了一下replace的用法才明白,原來replace不像想象中的那么簡單
    2013-04-04

最新評論