亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

Javascript的閉包詳解

2024-05-06 16:12:55
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了Javascript的閉包詳解,需要的朋友可以參考下
 
 

前言:還是一篇入門文章。Javascript中有幾個非常重要的語言特性——對象、原型繼承、閉包。其中閉包 對于那些使用傳統靜態語言C/C++的程序員來說是一個新的語言特性。本文將以例子入手來介紹Javascript閉包的語言特性,并結合一點 ECMAScript語言規范來使讀者可以更深入的理解閉包。

注:本文是入門文章,例子素材整理于網絡,如果你是高手,歡迎針對文章提出技術性建議和意見。本文討論的是Javascript,不想做語言對比,如果您對Javascript天生不適,請自行繞道。

什么是閉包
閉包是什么?閉包是Closure,這是靜態語言所不具有的一個新特性。但是閉包也不是什么復雜到不可理解的東西,簡而言之,閉包就是:

閉包就是函數的局部變量集合,只是這些局部變量在函數返回后會繼續存在。
閉包就是就是函數的“堆棧”在函數返回后并不釋放,我們也可以理解為這些函數堆棧并不在棧上分配而是在堆上分配
當在一個函數內定義另外一個函數就會產生閉包
上面的第二定義是第一個補充說明,抽取第一個定義的主謂賓——閉包是函數的‘局部變量'集合。只是這個局部變量是可以在函數返回后被訪問。(這個不是官方定義,但是這個定義應該更有利于你理解閉包)

做為局部變量都可以被函數內的代碼訪問,這個和靜態語言是沒有差別。閉包的差別在于局部變變量可以在函數執行結束后仍然被函數外的代碼訪問。這意味 著函數必須返回一個指向閉包的“引用”,或將這個”引用”賦值給某個外部變量,才能保證閉包中局部變量被外部代碼訪問。當然包含這個引用的實體應該是一個 對象,因為在Javascript中除了基本類型剩下的就都是對象了??上У氖?,ECMAScript并沒有提供相關的成員和方法來訪問閉包中的局部變 量。但是在ECMAScript中,函數對象中定義的內部函數(inner function)是可以直接訪問外部函數的局部變量,通過這種機制,我們就可以以如下的方式完成對閉包的訪問了。

 

復制代碼代碼如下:

function greeting(name) {
    var text = 'Hello ' + name; // local variable
    // 每次調用時,產生閉包,并返回內部函數對象給調用者
    return function() { alert(text); }
}
var sayHello=greeting("Closure");
sayHello()  // 通過閉包訪問到了局部變量text

 

上述代碼的執行結果是:Hello Closure,因為sayHello()函數在greeting函數執行完畢后,仍然可以訪問到了定義在其之內的局部變量text。

好了,這個就是傳說中閉包的效果,閉包在Javascript中有多種應用場景和模式,比如Singleton,Power Constructor等這些Javascript模式都離不開對閉包的使用。

ECMAScript閉包模型
ECMAScript到底是如何實現閉包的呢?想深入了解的親們可以獲取ECMAScript 規范進行研究,我這里也只做一個簡單的講解,內容也是來自于網絡。

在ECMAscript的腳本的函數運行時,每個函數關聯都有一個執行上下文場景(Execution Context) ,這個執行上下文場景中包含三個部分

文法環境(The LexicalEnvironment)
變量環境(The VariableEnvironment)
this綁定
其中第三點this綁定與閉包無關,不在本文中討論。文法環境中用于解析函數執行過程使用到的變量標識符。我們可以將文法環境想象成一個對象,該對 象包含了兩個重要組件,環境記錄(Enviroment Recode),和外部引用(指針)。環境記錄包含包含了函數內部聲明的局部變量和參數變量,外部引用指向了外部函數對象的上下文執行場景。全局的上下文 場景中此引用值為NULL。這樣的數據結構就構成了一個單向的鏈表,每個引用都指向外層的上下文場景。

例如上面我們例子的閉包模型應該是這樣,sayHello函數在最下層,上層是函數greeting,最外層是全局場景。如下圖:  因此當sayHello被調用的時候,sayHello會通過上下文場景找到局部變量text的值,因此在屏幕的對話框中顯示出”Hello Closure” 變量環境(The VariableEnvironment)和文法環境的作用基本相似,具體的區別請參看ECMAScript的規范文檔。

閉包的樣列
前面的我大致了解了Javascript閉包是什么,閉包在Javascript是怎么實現的。下面我們通過針對一些例子來幫助大家更加深入的理解閉包,下面共有5個樣例,例子來自于JavaScript Closures For Dummies(鏡像)。 例子1:閉包中局部變量是引用而非拷貝

 

復制代碼代碼如下:

function say667() {
    // Local variable that ends up within closure
    var num = 666;
    var sayAlert = function() { alert(num); }
    num++;
    return sayAlert;
}
 
var sayAlert = say667();
sayAlert()

 

因此執行結果應該彈出的667而非666。

例子2:多個函數綁定同一個閉包,因為他們定義在同一個函數內。

 

復制代碼代碼如下:

function setupSomeGlobals() {
    // Local variable that ends up within closure
    var num = 666;
    // Store some references to functions as global variables
    gAlertNumber = function() { alert(num); }
    gIncreaseNumber = function() { num++; }
    gSetNumber = function(x) { num = x; }
}
setupSomeGlobals(); // 為三個全局變量賦值
gAlertNumber(); //666
gIncreaseNumber();
gAlertNumber(); // 667
gSetNumber(12);//
gAlertNumber();//12

 

例子3:當在一個循環中賦值函數時,這些函數將綁定同樣的閉包

 

復制代碼代碼如下:

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]();
    }
}

 

testList的執行結果是彈出item3 undefined窗口三次,因為這三個函數綁定了同一個閉包,而且item的值為最后計算的結果,但是當i跳出循環時i值為4,所以list[4]的結果為undefined.

例子4:外部函數所有局部變量都在閉包內,即使這個變量聲明在內部函數定義之后。

 

復制代碼代碼如下:

function sayAlice() {
    var sayAlert = function() { alert(alice); }
    // Local variable that ends up within closure
    var alice = 'Hello Alice';
    return sayAlert;
}
var helloAlice=sayAlice();
helloAlice();

 

執行結果是彈出”Hello Alice”的窗口。即使局部變量聲明在函數sayAlert之后,局部變量仍然可以被訪問到。

例子5:每次函數調用的時候創建一個新的閉包

 

復制代碼代碼如下:

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);
    }
}
closure1=newClosure(40,{someVar:'closure 1'});
closure2=newClosure(1000,{someVar:'closure 2'});
 
closure1(5); // num:45 anArray[1,2,3,45] ref:'someVar closure1'
closure2(-10);// num:990 anArray[1,2,3,990] ref:'someVar closure2'

 

閉包的應用
Singleton 單件:

 

復制代碼代碼如下:

var singleton = function () {
    var privateVariable;
    function privateFunction(x) {
        ...privateVariable...
    }
 
    return {
        firstMethod: function (a, b) {
            ...privateVariable...
        },
        secondMethod: function (c) {
            ...privateFunction()...
        }
    };
}();

 

這個單件通過閉包來實現。通過閉包完成了私有的成員和方法的封裝。匿名主函數返回一個對象。對象包含了兩個方法,方法1可以方法私有變量,方法2訪 問內部私有函數。需要注意的地方是匿名主函數結束的地方的'()',如果沒有這個'()'就不能產生單件。因為匿名函數只能返回了唯一的對象,而且不能被 其他地方調用。這個就是利用閉包產生單件的方法。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人黄色av免费在线观看| 日韩中文有码在线视频| 97精品免费视频| 欧美视频不卡中文| 国色天香2019中文字幕在线观看| 亚洲精品国精品久久99热一| 国产成人综合一区二区三区| 欧美日韩国产精品一区二区不卡中文| 欧美丰满少妇xxxxx做受| 亚洲在线免费视频| 亚洲久久久久久久久久久| 欧美日韩一区二区免费视频| 欧美丰满片xxx777| 亚洲精品suv精品一区二区| 一个人看的www欧美| 欧美黑人xxx| 欧美精品久久久久久久免费观看| 色偷偷888欧美精品久久久| 大胆欧美人体视频| 中文字幕久久久av一区| 日韩在线播放视频| 国产精品精品一区二区三区午夜版| 欧美有码在线视频| 51久久精品夜色国产麻豆| 97人人做人人爱| 日韩有码视频在线| 久久久精品2019中文字幕神马| 国产主播喷水一区二区| 欧美激情精品久久久久久大尺度| 亚洲欧美在线第一页| 亚洲老司机av| 亚洲综合精品一区二区| 国产在线一区二区三区| 欧美精品久久久久久久久| 成人免费xxxxx在线观看| 日本高清+成人网在线观看| 国产精品成人国产乱一区| 日韩久久精品成人| 亚洲免费av片| 日韩中文av在线| 亚洲精品自在久久| 日韩欧美在线视频免费观看| 日韩中文字幕免费看| 日韩精品极品毛片系列视频| 久久精品成人动漫| 8090理伦午夜在线电影| 性金发美女69hd大尺寸| 91精品国产99久久久久久| 日本乱人伦a精品| 欧美成人合集magnet| 2019最新中文字幕| 欧美日韩视频免费播放| 日韩欧美aⅴ综合网站发布| 一区二区福利视频| 国产精品入口夜色视频大尺度| 国模精品视频一区二区三区| 日韩美女视频在线观看| 91精品国产一区| 美女福利视频一区| 欧美成人全部免费| 91精品国产高清久久久久久久久| 国产日韩在线免费| 久久视频中文字幕| 亚洲国产精品va在线看黑人| 国产一区二区三区中文| 欧美影院在线播放| 成人综合网网址| 国产精品九九久久久久久久| 欧美自拍视频在线观看| 国产999精品视频| 欧美在线一级va免费观看| 51ⅴ精品国产91久久久久久| 日韩国产高清视频在线| 精品日本高清在线播放| 久久久久久亚洲精品| 欧美最猛性xxxxx(亚洲精品)| 欧美色欧美亚洲高清在线视频| 日韩精品中文字幕视频在线| 精品动漫一区二区| 97精品国产97久久久久久春色| 伊人久久久久久久久久久久久| 国产国产精品人在线视| 国产日韩av在线播放| 亚洲护士老师的毛茸茸最新章节| 日韩在线视频观看正片免费网站| 91国产中文字幕| 亚洲欧美中文另类| 精品国产乱码久久久久久婷婷| 91免费视频网站| 精品亚洲一区二区三区在线播放| 琪琪亚洲精品午夜在线| 性欧美在线看片a免费观看| 欧美电影免费观看电视剧大全| 国产精品69精品一区二区三区| 成人av.网址在线网站| 国产一区香蕉久久| 欧美专区国产专区| 亚洲视频在线观看网站| 日韩在线精品一区| 日韩激情av在线播放| 中文字幕日韩在线视频| 国产a∨精品一区二区三区不卡| 亚洲区中文字幕| 国产精品十八以下禁看| 亚洲精品美女在线观看播放| 97色在线视频| 国产日韩欧美在线播放| 欧美猛男性生活免费| 在线播放国产一区二区三区| 丝袜美腿精品国产二区| 欧美激情性做爰免费视频| 欧美在线国产精品| 久久99视频精品| 在线观看欧美成人| 日韩美女av在线免费观看| 中国日韩欧美久久久久久久久| 久久精品亚洲国产| 久久综合久中文字幕青草| 色噜噜狠狠狠综合曰曰曰| 久久综合免费视频影院| 国产区亚洲区欧美区| 岛国av在线不卡| 中文字幕不卡在线视频极品| 亚洲aⅴ日韩av电影在线观看| 亚洲精品动漫久久久久| 一区二区三区美女xx视频| 久久久国产精彩视频美女艺术照福利| 国产日韩欧美在线视频观看| 日韩精品在线看| 成人妇女免费播放久久久| 国产深夜精品福利| 色妞在线综合亚洲欧美| 亚洲大胆美女视频| 亚洲黄色av女优在线观看| 欧美中文在线字幕| 一本久久综合亚洲鲁鲁| 国产深夜精品福利| 亚洲一区二区三区乱码aⅴ| 欧美精品一本久久男人的天堂| 97欧美精品一区二区三区| 亚洲国内精品视频| 欧美激情在线观看| 亚洲最大成人在线| 久久成人在线视频| 国产亚洲欧美另类中文| 国产午夜精品免费一区二区三区| 色偷偷av亚洲男人的天堂| 日韩午夜在线视频| 国内精品国产三级国产在线专| 91精品视频免费| 高潮白浆女日韩av免费看| 91国产精品视频在线| 精品美女永久免费视频| 亚洲风情亚aⅴ在线发布| 亚洲www永久成人夜色| 欧美巨大黑人极品精男| 黄色一区二区三区| 在线观看欧美日韩国产| 日韩欧美国产高清91| 日韩免费看的电影电视剧大全| 久久精品最新地址| 亚洲图片在线综合| 国产精品福利网| 日韩电影大全免费观看2023年上|