摘要:閉包閉包的特點就是內(nèi)部匿名函數(shù)可以訪問外部函數(shù)作用域的變量和方法變量對象。閉包的主要表現(xiàn)形式就是匿名函數(shù),但是兩者并不是等價的。中是沒有塊級作用域的,為了在中引入塊級作用域,可以使用匿名函數(shù)模擬塊級作用域。
在介紹閉包之前,首先解釋在隨后的測試實例中會使用的assert測試函數(shù),這個方法有別于alert()測試,有很大的改進(jìn)。
assert()測試方法用法:assert(condition, “string”); 把字符串顯示在頁面上,根據(jù)條件是否成立決定顯示的顏色,條件為真就顯示為綠色,否則為紅色。
閉包的特點就是內(nèi)部匿名函數(shù)可以訪問外部函數(shù)作用域的變量和方法(變量對象)。一般來說,當(dāng)函數(shù)執(zhí)行完畢后, 局部活動對象(函數(shù)的變量對象)就會被銷毀,內(nèi)存中僅保留全局作用域(全局執(zhí)行環(huán)境的變量對象)。但是閉包創(chuàng)建時,內(nèi)部函數(shù)的作用域鏈中會一直引用著外部函數(shù)的活動對象,這個活動對象一直被引用而不能被回收,一直占用內(nèi)存,容易造成內(nèi)存泄漏。
閉包的主要表現(xiàn)形式就是匿名函數(shù),但是兩者并不是等價的。閉包的常見用法就是封裝一些私有變量,也就是限制這些變量的作用域。任何在函數(shù)中創(chuàng)建的變量都是私有變量,因為在函數(shù)外部不能訪問這些變量,私有變量包括函數(shù)的參數(shù)、局部變量、在函數(shù)內(nèi)部定義的其他函數(shù)。有權(quán)在外部訪問私有變量的公有方法被稱為特權(quán)方法,第一種創(chuàng)建特權(quán)方法的的方式是在構(gòu)造函數(shù)中定義特權(quán)方法,如下:
function Ninjia(){ //私有屬性 var feints = 0; //特權(quán)方法 this.getFeints = function(){ return feints; }; this.feintNum = function(){ feints++; }; } var ninjia= new Ninjia(); ninjia.feintNum(); assert(ninjia.getFeints() == 1, "can accesss interal variable");//可以通過特權(quán)方法訪問 assert(ninjia.feints, "can access private variable");//無法訪問
可以看出,特權(quán)方法之所以能夠訪問構(gòu)造函數(shù)中定義的所有變量和函數(shù),根本原因在于,特權(quán)方法就是一個閉包,可以通過作用域鏈訪問外部函數(shù),也就是構(gòu)造函數(shù)。通過構(gòu)造函數(shù)定義特權(quán)方法的缺點在于使用構(gòu)造函數(shù)創(chuàng)建自定義對象的固有弊端,那就是方法(函數(shù)對象)的重復(fù)創(chuàng)建。
第二種方式是在私有作用域中定義私有變量或私有函數(shù),同樣也可以創(chuàng)建特權(quán)方法。
首先介紹私有作用域。JavaScript中是沒有塊級作用域的,為了在JavaScript中引入塊級作用域,可以使用匿名函數(shù)模擬塊級作用域。為什么大費周折整出塊級作用域呢?因為有了塊級作用域,每個開發(fā)人員都可以在塊級作用域中定義自己的變量,而不用擔(dān)心會搞亂全局作用域,過多的全局作用域變量核函數(shù)會導(dǎo)致命名沖突。匿名函數(shù)用作塊級作用域被稱為私有作用域(private scope),這個匿名函數(shù)實際上就是一個閉包,它可以訪問自己內(nèi)部活動對象,函數(shù)執(zhí)行完成即銷毀,不占用內(nèi)存,語法如下:
(function () { //塊級作用域 })();
上述代碼首先將函數(shù)聲明包含在圓括號中,這表示這段代碼實際上是一個函數(shù)表達(dá)式,緊隨其后的圓括號會立即調(diào)用這個函數(shù)。
以下實例表明,私有作用域的變量不可由外部訪問。
var outputNum = function(count){ (function(){ for (var i=0; i然后介紹往私有作用域中添加私有變量和函數(shù),同時定義特權(quán)方法。
(function(){ //私有屬性 var name=""; //構(gòu)造函數(shù) Person = function(value){ name = value; }; //構(gòu)造函數(shù)原型方法-->特權(quán)方法 Person.prototype.getName = function(){ return name; } Person.prototype.setName = function(value){ name = value; } })(); var person1= new Person("zhang"); alert(person1.getName());//zhang person1.setName("wang"); alert(person1.getName());//wang var person2= new Person("li"); alert(person1.getName());//li,實例間的屬性共享這種方法的主要弊端在于,私有變量實際上變成了所有靜態(tài)的由所有實例共享的屬性,也就是說,在一個實例上調(diào)用方法改變私有變量值后,會在另一個變量上體現(xiàn)出來。
閉包的使用實例: 1)Ajax回調(diào)函數(shù)中的閉包:jQuery("#testButton").click(function(){ //#1 var elem$ = jQuery("#testSubject"); //#2 elem$.html("Loading..."); //#3 jQuery.ajax({ url: "test.html", success: function(html){ //#4 assert(elem$, //elem$是外部變量,匿名函數(shù)式回調(diào)函數(shù) "We can see elem$, via the closure for this callback."); elem$.html(html); } }); });2)計時器回調(diào)函數(shù)中的閉包:function animateIt(elementId){ var elem = document.getElementById(elementId); var tick = 0; var timer = setInterval(function(){ if (tick <100){ elem.style.top = tick+"px"; elem.style.left = tick+"px"; tick++; } else{ clearInterval(timer); assert(tick == 100, "Tick accessd via a closure"); assert(elem, "elem accesse via a closure"); assert(timer, "timer reference accessed via a closure"); } }, 10); } animateIt("box");通過在函數(shù)內(nèi)部定義變量(本例中是elem, tick, timer),并依靠閉包,可以在計時器回調(diào)函數(shù)調(diào)用的時候進(jìn)行使用,這樣,每個動畫就有自己的私有變量(elem, tick, timer一次定義,多次使用)。如果在全局作用域中設(shè)置變量并且有多個動畫需要設(shè)置,為了避免混淆,需要為每個動畫設(shè)置3個變量。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/50121.html
摘要:閉包閉包的特點就是內(nèi)部匿名函數(shù)可以訪問外部函數(shù)作用域的變量和方法變量對象。閉包的主要表現(xiàn)形式就是匿名函數(shù),但是兩者并不是等價的。中是沒有塊級作用域的,為了在中引入塊級作用域,可以使用匿名函數(shù)模擬塊級作用域。 在介紹閉包之前,首先解釋在隨后的測試實例中會使用的assert測試函數(shù),這個方法有別于alert()測試,有很大的改進(jìn)。 assert()測試方法 #...
摘要:第二例這段代碼是用來做將斷言測試分組的,代碼多了些,問題自然也更多了些。首先作者使用了自執(zhí)行方法封閉了作用域,使用來指向全局對象,進(jìn)而產(chǎn)生全局可訪問的屬性。沒想到,久負(fù)盛名,豆瓣評分的大作,作者的光環(huán),代碼風(fēng)格居然是如此的不謹(jǐn)慎。 第二章中 作者給了幾個簡單的斷言例子,思路與方向是極不錯的,創(chuàng)造JQ的大神,思想高度絕對無法讓我質(zhì)疑的,但是代碼的功底細(xì)節(jié),實在是讓人不敢恭維。 第一例: ...
摘要:全局的函數(shù)第個對象第個對象作為構(gòu)造器進(jìn)行調(diào)用也就是利用運算符進(jìn)行調(diào)用。與操作的共同使用只有通過操作產(chǎn)生的對象,可以使用構(gòu)造器函數(shù)原型鏈上的內(nèi)容,否則對象只能使用自己原型鏈上的內(nèi)容。 今天這個話題是因為這幾天看了《JavaScript忍者秘籍》,感覺這本書把這幾個內(nèi)容講的蠻透徹了,特撰本文,以便日后翻閱。(應(yīng)該都會以知識點的形式給出吧。) 函數(shù) 1.【基本類型】 JavaScript中函...
摘要:無處不在的理解語言與其他主流語言相比,函數(shù)式語言的血統(tǒng)更多一些。函數(shù)式語言一類程序設(shè)計語言,是一種非馮諾伊曼式的程序設(shè)計語言。函數(shù)式語言主要成分是原始函數(shù),定義函數(shù)和函數(shù)型。性能分析內(nèi)置對象上的和方法。 無處不在的JavaScript 理解JavaScript語言 與其他主流語言相比,JavaScript函數(shù)式語言的血統(tǒng)更多一些。 函數(shù)式語言一類程序設(shè)計語言,是一種非馮.諾伊曼式的程序...
摘要:但是函數(shù)返回了內(nèi)部函數(shù),內(nèi)部函數(shù)會隨時訪問變量所以垃圾回收機(jī)制是不會回收函數(shù)的內(nèi)部作用域的,這就是閉包的含義。也就是函數(shù)在定義的詞法作用域以外的地方被調(diào)用,閉包使得函數(shù)可以繼續(xù)訪問定義時的詞法作用域。 初學(xué)JavaScript閉包時,閉包這個概念在我眼里及其的神秘,也不知道這個東西在講什么,尤其某些地方的閉包概念定義的非常抽象,屬于那種本來你可能明白這個概念,看了反而又把你給繞糊涂...
閱讀 664·2021-11-11 16:55
閱讀 2166·2021-11-11 16:55
閱讀 1958·2021-11-11 16:55
閱讀 2350·2021-10-25 09:46
閱讀 1614·2021-09-22 15:20
閱讀 2295·2021-09-10 10:51
閱讀 1712·2021-08-25 09:38
閱讀 2626·2019-08-30 12:48