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