(转)《AS3 Expert》动态语言的基石:函数闭包
《AS3 Expert》動態語言的基石:函數閉包
Admin
2010年6月19日名人名言:時間,每天得到的都是二十四小時,可是一天的時間給勤勉的人帶來智慧和力量,給懶散的人只留下一片悔恨。——魯迅
?原文:http://sban.biz/216
閉包(Closure)是函數(或方法)及其執行環境的組合體,它不僅包括函數(或方法)本身,也包括函數(或方法)運行時的上下文詞匯環境。閉包是所有動態語言的基石,閉包實現了函數(或方法)可以作為參數傳遞給函數(或方法)。
?
1,用一個代碼實驗例示閉包概念
在AS3中,共種三種閉包:
1)函數閉包(Function Closure)
2)方法閉包(Method Closure)
3)類閉包(Class Closure)
public class Closure extends Sprite
{
public function Closure()
{
super();
init();
}
private var author :String = "sban";
private var onMouseClick2 :Function = function(e :MouseEvent) : void
{
trace("author:" + author, "this:" + this);//author:undefined this:[object global]
};
private function init() :void
{
var onMouseClick1 : Function = function(e :MouseEvent) : void
{
trace("author:" + author, "this:" + this);//author:sban this:[object global]
};
this.stage.addEventListener(MouseEvent.CLICK, onMouseClick2);
}
private function onMouseClick(e :MouseEvent) :void
{
trace("author:" + author, "this:" + this);//author:sban this:[object Closure]
}
}
?
在上例代碼中,分別以onMouseClick,onMouseClick1,onMouseClick2為listener向stage添加click事件監聽,trace結果如代碼中注釋。其中,onMouseClick是方法閉包,onMouseClick1與onMouseClick2是函數閉包。這里有一個問題,為什么在onMouseClick2中author的輸出結果是undefined?
2,三類閉包的區分
在AS3中,任何一個函數(或方法)調用,至少會有一個this參數,這幾乎是所有動態語言一慣的規則,不同的是,有的語言對程序員是可見的,如Python,有的則不可見,如AS3。
1) 方法閉包
所有類實例的方法,作為參數傳遞時,均是方法閉包,隱匿的第一個this參數永遠是類實例本身,如上例代碼中的onMouseClick便是方法閉包,所以它的this輸出為[object Closure]。
2) 函數閉包
所有匿名方法(包括局部變量方法,類變量方法,見上),全局方法(包括位于根包下的全局方法,位于子包下的全局方法,見下)均是函數閉包,所有函數閉包的第一個函數如果是null,將被默認替換為Global對象,所以我們看到的輸出均是[object global] 。
package
{
import flash.events.MouseEvent;
function onMouseClick3(e :MouseEvent) :void
{
trace("this:" + this);//this:[object global]
}
}
package sban.as3Expert
{
import flash.events.MouseEvent;
public function onMouseClick4(e :MouseEvent)
{
trace("this:" + this);//this:[object global]
}
}
?
對于位于子包下的函數,可以這樣直接使用:
this.stage.addEventListener(MouseEvent.CLICK, sban.as3Expert.onMouseClick4);
3)類閉包
這是三類閉包中最簡單的一種,也是最容易區分的一種,可能也是價值最低的一種,貌似根本不應該歸為閉包類別。在AS3中,所有顯式對象類型轉換均是類閉包,如下:
//if obj is Closure which type anotation is Object
var obj1 :Closure = Closure(obj);
Closure在這里不是操作符,也不是別的什么東西,在這里應該把它理解為一個特殊的方法。這個方法第一個參數仍然為this,第二個參數是將被作類型轉換的對象,在上例代碼中為obj。
3,改變函數閉包的this參數的一種情況
在函數閉包中,this參數(null)通常被默默置換為global對象,在某些情況下,程序員可以傳遞真實的this參數進去,而不是null,從而避免被替換為global對象。
在Array的forEach, every, map, some, filter這些API中,第一個參數為函數對象,第二個參數為第一個參數的this對象,當程序員指定第二個參數時,便可以在第一個函數內訪問this上下文環境的變量,如果不指定,便不能再其內使用this。
public function ArrayForEachThis()
{
super();
var arr :Array = [1,2,3];
arr.forEach(
function (item :int,index :int=-1,arr :Array = null) :void
{
trace(item, this.author)
}
//,this
);
}
private var author :String = "sban";
編碼規范:在使用Array的forEach, every, map, some, filter這些API時,必須在第二個參數位傳遞this進去。
4,為什么在onMouseClick2中author的輸出是undefined?
所有AS3程序員都應當知道,在AS3運行時,有一個作用域鏈,該作用域鏈自global始,在運行時變量首先從最近的鏈點查找,如果未找到,再向上查找,直到找到或到達global鏈點。
onMouseClick2函數的運行時作用域鏈為:
onMouseClick2閉包->global
在這個鏈條內,根本不存在author變量,所以onMouseClick2的輸出為undefined。
而onMouseClick1的作用域鏈為:
onMouseClick1->init->Closure->global
onMouseClick的作用域鏈為:
onMouseClick->Closure->global
這兩個作用域鏈均包括author變量,所以onMouseClick1與onMouseClick均不會輸出undefined。
作用域鏈的節點包括閉包對象,但不僅包括它。
sban 2009/5/15 北京。轉載請注明作者及出處,非商用。
作者:sban
出處:http://sban.biz
本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
時間,每天得到的都是二十四小時,可是一天的時間給勤勉的人帶來智慧和力量,給懶散的人只留下一片悔恨。——魯迅
來源:http://www.cnblogs.com/sban/archive/2010/05/27/1745357.html 補充可有意思的例子: package {import flash.display.Sprite;import flash.events.MouseEvent;public class Main extends Sprite{public function Main(){//func1(2);//func1(3);var b:int=1;func1(b);b++;func1(b);}public function func1(a:int):void{stage.addEventListener(MouseEvent.CLICK,func2);function func2(e:MouseEvent):void{trace(a);}return;}} }
在場景上按一下,結果:
1
2
充分說明了運行時保存上下文環境的特性。
轉載于:https://www.cnblogs.com/wonderKK/archive/2012/08/01/2618800.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的(转)《AS3 Expert》动态语言的基石:函数闭包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MongoDB监控及报警
- 下一篇: Java蓝桥杯02——第二题集锦:生日蜡