İşlevler
, belirli görevleri gerçekleştirdiğiniz ve programınızda yeniden kullanılabilen kod bloklarıdır. ActionScript 3.0'da iki tür işlev vardır:
yöntemler
ve
işlev kapanışları
. Bir işlevin yöntem veya işlev kapanışı olarak adlandırılması, işlevin tanımlandığı bağlama bağlıdır. Bir işlevi sınıf tanımının parçası olarak tanımlarsanız veya bunu bir nesne örneğine eklerseniz bu işlev yöntem olarak adlandırılır. Bir işlev başka bir şekilde tanımlanırsa, işlev kapanışı olarak adlandırılır.
İşlevler ActionScript'te her zaman çok önemli olmuştur. Örneğin, ActionScript 1.0'da
class
anahtar sözcüğü yoktu, bu nedenle “sınıflar” yapıcı işlevleri tarafından tanımlanırdı. Bu nedenle dile
class
anahtar sözcüğü eklenmiş olsa da, dilin sunması gereken şeylerden tam anlamıyla yararlanmak istiyorsanız, işlevlerin düzgün bir şekilde anlaşılması hala çok önemlidir. ActionScript işlevlerinin C++ veya Java gibi dillerdeki işlevlere benzer şekilde davranmasını bekleyen programcılar için bu güçlük yaratabilir. Temel işlev tanımı ve çağırma işlemi deneyimli programcılar için güçlük oluşturmasa da, ActionScript işlevlerinin daha gelişmiş olan bazı özelliklerinin açıklanması gerekir.
Temel işlev kavramları
İşlevleri çağırma
Bir işlevin, ardından parantez operatörü (
()
) gelen tanımlayıcısını kullanarak o işlevi çağırabilirsiniz. İşleve göndermek istediğiniz herhangi bir işlev parametresini kapsamak için parantez operatörünü kullanırsınız. Örneğin,
trace()
işlevi ActionScript 3.0'da üst düzeyli bir işlevdir:
trace("Use trace to help debug your script");
Herhangi bir parametre içermeyen bir işlevi çağırıyorsanız, boş bir parantez çifti kullanmanız gerekir. Örneğin, rastgele bir sayı oluşturmak için, herhangi bir parametre almayan
Math.random()
yöntemini kullanabilirsiniz:
var randomNum:Number = Math.random();
Kendi işlevlerinizi tanımlama
ActionScript 3.0'da bir işlevi tanımlamanın iki yolu vardır: bir işlev deyimini veya işlev ifadesini kullanabilirsiniz. Seçtiğiniz teknik, daha statik veya daha dinamik bir programlama stili seçmenize bağlıdır. Statik veya katı mod programlamayı tercih ediyorsanız işlevlerinizi işlev deyimleriyle tanımlayın. Aksini yapmanız gerekiyorsa, işlevlerinizi işlev ifadeleriyle tanımlayın. İşlev ifadeleri, dinamik veya standart mod programlamada daha sık kullanılır.
İşlev deyimleri
İşlev deyimleri, katı modda işlevleri tanımlamak için tercih edilen tekniktir. Bir işlev deyimi,
function
anahtar sözcüğüyle başlar ve şunlarla devam eder:
-
İşlev adı
-
Parantez içindeki virgül sınırlı bir listede yer alan parametreler
-
İşlev gövdesi, başka bir deyişle, işlev çağrıldığında çalıştırılacak olan, küme parantezi içine alınmış ActionScript kodu
Örneğin, aşağıdaki kod, bir parametreyi tanımlayan bir işlev oluşturur ve ardından parametre değeri olarak “
hello"
dizesini kullanarak işlevi çağırır:
function traceParameter(aParam:String)
{
trace(aParam);
}
traceParameter("hello"); // hello
İşlev ifadeleri
Bir işlev bildirmenin ikinci yolu, aynı zamanda bazen bir işlev değişmezini veya adsız işlevi çağıran işlev ifadesiyle bir atama deyiminin kullanılmasıdır. Bu, önceki ActionScript sürümlerinde yaygın olarak kullanılan daha ayrıntılı bir yöntemdir.
İşlev ifadesi içeren bir atama deyimi,
var
anahtar sözcüğüyle başlar ve şunlarla devam eder:
-
İşlev adı
-
İki nokta operatörü (
:
)
-
Veri türünü belirtecek
Function
sınıfı
-
Atama operatörü (
=
)
-
function
anahtar sözcüğü
-
Parantez içindeki virgül sınırlı bir listede yer alan parametreler
-
İşlev gövdesi, başka bir deyişle, işlev çağrıldığında çalıştırılacak olan, küme parantezi içine alınmış ActionScript kodu
Örneğin, aşağıdaki kod, bir işlev ifadesi kullanarak
traceParameter
işlevini bildirir:
var traceParameter:Function = function (aParam:String)
{
trace(aParam);
};
traceParameter("hello"); // hello
İşlev deyiminde yaptığınız gibi bir işlev adı belirtmediğinize dikkat edin. İşlev ifadeleri ile işlev deyimleri arasındaki başka bir önemli fark, işlev ifadesinin deyim yerine bir ifade olmasıdır. Başka bir deyişle, bir işlev ifadesi, işlev deyimi gibi tek başına duramaz. İşlev ifadesi yalnızca bir deyimin parçası olarak kullanılabilir ve bu genellikle bir atama deyimi olur. Aşağıdaki örnek, bir dizi örneğine atanmış işlev ifadesini gösterir:
var traceArray:Array = new Array();
traceArray[0] = function (aParam:String)
{
trace(aParam);
};
traceArray[0]("hello");
Deyimler ile ifadeler arasında tercih yapma
Genel bir kural olarak, belirli koşullar bir ifade kullanımını gerektirmediği sürece, işlev deyimini kullanın. İşlev deyimleri daha az ayrıntılıdır ve katı mod ile standart mod arasında işlev ifadelerine göre daha tutarlı bir deneyim sağlar.
İşlev deyimlerinin okunması, işlev ifadelerini içeren atama deyimlerinden daha kolaydır. İşlev deyimleri kodunuzu daha kısa hale getirir; hem
var
hem de
function
anahtar sözcüklerini kullanmanızı gerektiren işlev ifadelerinden daha az karmaşıktır.
İşlev deyimleri, bir işlev deyimi kullanılarak bildirilmiş bir yöntemi çağırmak için nokta sözdizimini hem sıkı hem de standart modda kullanabilmenize olanak sağladığından, iki derleyici modu arasında daha tutarlı bir deneyim sağlar. Bu bir işlev ifadesiyle bildirilmiş yöntemler için her zaman geçerli değildir. Örneğin, aşağıdaki kod, iki yöntemle Example adında bir sınıfı tanımlar: bir işlev ifadesiyle bildirilen
methodExpression()
yöntemi ve bir işlev deyimiyle çağrılan
methodStatement()
yöntemi. Sıkı modda,
methodExpression()
yöntemini çağırmak için nokta sözdizimini kullanamazsınız.
class Example
{
var methodExpression = function() {}
function methodStatement() {}
}
var myEx:Example = new Example();
myEx.methodExpression(); // error in strict mode; okay in standard mode
myEx.methodStatement(); // okay in strict and standard modes
İşlev deyimleri, çalışma zamanını veya dinamik davranışı esas alan programlamalar için daha uygun olarak değerlendirilir. Katı modu kullanmayı tercih ediyorsanız ancak diğer yandan bir işlev ifadesiyle bildirilmiş bir yöntemi çağırmanız gerekiyorsa, iki teknikten herhangi birini kullanabilirsiniz. İlk olarak, nokta (
.
) operatörü yerine (
[]
) köşeli parantezleri kullanarak yöntemi çağırabilirsiniz. Aşağıdaki yöntem çağrısı hem katı modda hem de standart modda başarılı olur:
myExample["methodLiteral"]();
İkinci olarak, sınıfın tamamını dinamik sınıf olarak bildirebilirsiniz. Bu, nokta operatörünü kullanarak yöntemi çağırmanıza olanak sağlasa da, bunun dezavantajı, söz konusu sınıfın tüm örnekleri için bazı katı mod işlevselliğinden taviz vermenizdir. Örneğin, bir dinamik sınıf örneğinde tanımsız bir özelliğe erişmeyi denerseniz, derleyici bir hata oluşturmaz.
İşlev ifadelerinin kullanışlı olduğu bazı koşullar vardır. İşlev ifadelerinin yaygın olarak kullanıldığı koşullardan biri, yalnızca bir defa kullanılan ve sonra atılan işlevlerdir. Daha az yaygın olarak da bir işlevin bir prototip özelliğine eklenmesi için kullanılabilir. Daha fazla bilgi için, bkz.
Prototip nesnesi
.
İşlev deyimleri ile işlev ifadeleri arasında, kullanılacak tekniği seçerken dikkate almanız gereken iki küçük fark vardır. Birinci fark, işlev ifadelerinin bellek yönetimi ve çöp toplamaya göre nesneler olarak bağımsız şekilde bulunmamasıdır. Başka bir deyişle, dizi öğesi veya nesne özelliği gibi başka bir nesneye bir işlev ifadesi atadığınızda, kodunuzda yalnızca o işlev ifadesine başvuru oluşturursunuz. İşlev ifadenizin eklendiği dizi veya nesne kapsam dışına çıkarsa ya da artık kullanılamazsa, işlev ifadesine daha fazla erişemezsiniz. Dizi veya nesne silinirse, işlev ifadesinin kullandığı bellek, çöp toplama için uygun olur; başka bir deyişle, bellek başka amaçlar için geri istenmeye ve yeniden kullanılmaya uygun olur.
Aşağıdaki örnek, bir işlev ifadesi için, ifadenin atandığı özellik silindikten sonra işlevin artık kullanılamadığını gösterir. Test sınıfı dinamiktir, başka bir deyişle, bir işlev ifadesi içeren
functionExp
adında bir özellik ekleyebilirsiniz.
functionExp()
işlevi nokta operatörüyle çağrılabilir, ancak
functionExp
özelliği silindikten sonra artık işleve erişilemez.
dynamic class Test {}
var myTest:Test = new Test();
// function expression
myTest.functionExp = function () { trace("Function expression") };
myTest.functionExp(); // Function expression
delete myTest.functionExp;
myTest.functionExp(); // error
Diğer bir yandan, işlev ilk olarak bir işlev deyimiyle tanımlanırsa, kendi nesnesi olarak varolur ve siz işlevin eklendiği özelliği sildikten sonra da işlev varolmaya devam eder.
delete
operatörü yalnızca nesnelerin özelliklerinde çalışır, bu nedenle,
stateFunc()
işlevini silme çağrısı çalışmaz.
dynamic class Test {}
var myTest:Test = new Test();
// function statement
function stateFunc() { trace("Function statement") }
myTest.statement = stateFunc;
myTest.statement(); // Function statement
delete myTest.statement;
delete stateFunc; // no effect
stateFunc();// Function statement
myTest.statement(); // error
İşlev deyimleri ile işlev ifadeleri arasındaki ikinci bir fark, işlev deyimlerinin, işlev deyiminden önce görüntülenen deyimler de dahil olmak üzere, tanımlandıkları kapsamda varolmalarıdır. İşlev ifadeleri, bunun tersine yalnızca sonraki deyimler için tanımlanır. Örneğin, aşağıdaki kod tanımlanmadan önce
scopeTest()
işlevini başarıyla çağırırsa:
statementTest(); // statementTest
function statementTest():void
{
trace("statementTest");
}
İşlev ifadeleri, tanımlanmadan önce kullanılamaz, bu nedenle de aşağıdaki kod bir çalışma zamanı hatası oluşturur:
expressionTest(); // run-time error
var expressionTest:Function = function ()
{
trace("expressionTest");
}
İşlevlerden değerleri döndürme
İşlevinizden bir değer döndürmek için, ardından döndürmek istediğiniz ifade veya değişmez değer gelecek şekilde
return
deyimini kullanın. Örneğin, aşağıdaki kod, parametreyi temsil eden bir ifade döndürür:
function doubleNum(baseNum:int):int
{
return (baseNum * 2);
}
return
deyiminin işlevi sonlandırdığına dikkat edin, böylece aşağıdaki gibi,
return
deyiminin altındaki deyimler çalıştırılmaz:
function doubleNum(baseNum:int):int {
return (baseNum * 2);
trace("after return"); // This trace statement will not be executed.
}
Katı modda, bir döndürme türü belirtmeyi seçerseniz, ilgili türde bir değer döndürmeniz gerekir. Örneğin, aşağıdaki kod geçerli bir değer döndürmediğinden, katı modda bir hata oluşturur:
function doubleNum(baseNum:int):int
{
trace("after return");
}
Yuvalanmış işlevler
İşlevleri yuvalayabilirsiniz, başka bir deyişle, işlevler diğer işlevler içinde bildirilebilir. Yuvalanmış işlevin başvurusu harici koda iletilmediği sürece, yuvalanmış bir işlev yalnızca üst işlevi içinde kullanılabilir. Örneğin, aşağıdaki kod,
getNameAndVersion()
işlevi içinde iki yuvalanmış işlev bildirir:
function getNameAndVersion():String
{
function getVersion():String
{
return "10";
}
function getProductName():String
{
return "Flash Player";
}
return (getProductName() + " " + getVersion());
}
trace(getNameAndVersion()); // Flash Player 10
Yuvalanmış işlevler harici koda iletildiğinde, işlev kapanışları olarak iletilir; başka bir deyişle, işlev tanımlandığında kapsamda olan tüm tanımlar işlevde saklanır. Daha fazla bilgi için, bkz.
İşlev kapsamı
.
İşlev parametreleri
ActionScript 3.0, dil kullanımında tecrübesiz olan programcılar için yeni gibi görünen bazı işlev parametreleri işlevleri sağlar. Değere veya başvuruya göre parametre iletme kavramı çoğu programcılara tanıdık gelse de,
arguments
nesnesi ve ... (rest)parametresi birçoğu için yeni olabilir.
Değere veya başvuruya göre argümanları iletme
Çoğu programlama dilinde, değere veya başvuruya göre argümanları iletme arasındaki ayrımın anlaşılması önemlidir; bu ayrım kodun tasarlanma şeklini etkileyebilir.
Değere göre iletilme, argüman değerinin, işlev içinde kullanılmak üzere yerel bir değişkene kopyalanması anlamına gelir. Başvuruya göre iletilme ise gerçek değerin değil, yalnızca argümanın bir başvurusunun iletilmesi anlamına gelir. Gerçek argümanın herhangi bir kopyası oluşturulmaz. Bunun yerine, argüman olarak iletilen değişkenin başvurusu oluşturulur ve işlev içinde kullanılmak üzere yerel değişkene atanır. Yerel değişken, işlev dışındaki bir değişkenin başvurusu olarak, size orijinal değişkenin değerini değiştirme yeteneği sağlar.
ActionScript 3.0'da, tüm değerler nesneler olarak saklandığından, tüm argümanlar başvuruya göre iletilir. Ancak, Boolean, Number, int, uint ve String gibi ilkel veri türlerine ait olan nesneler, değere göre iletilmiş gibi davranmasını sağlayan özel operatörlere sahiptir. Örneğin, aşağıdaki kod, her ikisi de int türünde olan
xParam
ve
yParam
adında iki parametreyi tanımlayan
passPrimitives()
adında bir işlev oluşturur. Bu parametreler,
passPrimitives()
işlevinin gövdesinde bildirilen yerel değişkenlere benzer. İşlev,
xValue
ve
yValue
argümanlarıyla çağrılırsa,
xParam
ve
yParam
parametreleri,
xValue
ve
yValue
tarafından temsil edilen int nesnelerinin başvurularıyla başlatılır. Argümanlar ilkel olduğundan, bunlar değere göre iletilmiş gibi davranır.
xParam
ve
yParam
öğeleri başlangıçta
xValue
ve
yValue
nesnelerini içerse de, işlev gövdesi içinde değişkenler üzerinde yapılan tüm değişiklikler bellekte değerlerin yeni kopyalarını oluşturur.
function passPrimitives(xParam:int, yParam:int):void
{
xParam++;
yParam++;
trace(xParam, yParam);
}
var xValue:int = 10;
var yValue:int = 15;
trace(xValue, yValue);// 10 15
passPrimitives(xValue, yValue); // 11 16
trace(xValue, yValue);// 10 15
passPrimitives()
işlevi içinde,
xParam
ve
yParam
değerleri artırılır ancak bu, son
trace
deyiminde gösterildiği gibi,
xValue
ve
yValue
değerlerini etkilemez. İşlevin içindeki
xValue
ve
yValue
öğeleri, bellekte, işlev dışında aynı addaki değişkenlerden ayrı olarak varolan yeni konumları işaret ettiğinden, parametreler
xValue
ve
yValue
değişkenleriyle aynı şekilde adlandırılsaydı da bu durum geçerli olurdu.
Diğer tüm nesneler; başka bir deyişle, ilkel veri türünde olmayan nesneler, her zaman başvuruya göre iletilir ve bu da size orijinal değişkenin değerini değiştirme yeteneği sağlar. Örneğin, aşağıdaki kod,
x
ve
y
olmak üzere iki özellikle
objVar
adında bir nesne oluşturur.
passByRef()
işlevine argüman olarak iletilen nesne. Nesne ilkel türde olmadığından, yalnızca başvuruya göre iletilmekle kalmaz aynı zamanda başvuru olmaya devam eder. Başka bir deyişle, işlev içindeki parametreler üzerinde yapılan değişiklikler, işlev dışındaki nesne özelliklerini etkiler.
function passByRef(objParam:Object):void
{
objParam.x++;
objParam.y++;
trace(objParam.x, objParam.y);
}
var objVar:Object = {x:10, y:15};
trace(objVar.x, objVar.y); // 10 15
passByRef(objVar); // 11 16
trace(objVar.x, objVar.y); // 11 16
objParam
parametresi, genel
objVar
değişkeniyle aynı nesneye başvurur. Örnekteki
trace
deyimlerinde de görebileceğiniz gibi,
objParam
nesnesinin
x
ve
y
özellikleri üzerinde yapılan değişiklikler,
objVar
nesnesinde yansıtılır.
Varsayılan parametre değerleri
ActionScript'te, bir işlev için
varsayılan parametre değerleri
bildirebilirsiniz. Varsayılan parametre değerleri içeren bir işleve yapılan çağrı, varsayılan değerleri içeren bir parametreyi çıkarırsa, o parametre için işlev tanımında belirtilen değer kullanılır. Varsayılan değerlere sahip tüm parametrelerin parametre listesinin sonuna yerleştirilmesi gerekir. Varsayılan değer olarak atanan değerlerin derleme zamanı sabitleri olması gerekir. Bir parametre için varsayılan bir değerin olması, o parametreyi etkili şekilde
isteğe bağlı parametre
yapar. Varsayılan değer içermeyen bir parametre,
zorunlu parametre
olarak değerlendirilir.
Örneğin, aşağıdaki kod üç parametre içeren bir işlev oluşturur, bu parametrelerin ikisi varsayılan değerleri içerir. Yalnızca bir parametreyle işlev çağrıldığında, parametrelerin varsayılan değerleri kullanılır.
function defaultValues(x:int, y:int = 3, z:int = 5):void
{
trace(x, y, z);
}
defaultValues(1); // 1 3 5
arguments nesnesi
Bir işleve parametreler iletildiğinde, işlevinize iletilen parametreler hakkındaki bilgilere erişmek için
arguments
nesnesini kullanabilirsiniz.
arguments
nesnesinin önemli yönlerinden bazıları şunlardır:
-
arguments
nesnesi, işleve iletilen tüm parametreleri içeren bir dizidir.
-
arguments.length
özelliği, işleve iletilen parametrelerin sayısını bildirir.
-
arguments.callee
özelliği, işlevin kendisine bir başvuru sağlar, bu da işlev ifadelerine yapılan yinelemeli çağrılar için kullanışlıdır.
Not:
Herhangi bir parametre
arguments
olarak adlandırılırsa veya ... (rest) parametresini kullanırsanız,
arguments
nesnesi kullanılamaz.
İşlev gövdesinde
arguments
nesnesine başvurulursa, ActionScript 3.0, işlev çağrılarının, işlev tanımında tanımlananlardan daha fazla parametre içermesine olanak tanır, ancak parametre sayısı, zorunlu parametre (ve isteğe bağlı olarak isteğe bağlı parametre) sayısıyla eşleşmezse, sıkı modda bir derleyici hatası oluşturur. İşlev tanımında tanımlansa da tanımlanmasa da, işleve iletilen herhangi bir parametreye erişmek için
arguments
nesnesinin dizi yönünü kullanabilirsiniz. Yalnızca standart modda derleme yapan aşağıdaki örnek,
traceArgArray()
işlevine iletilen tüm parametreleri izlemek için
arguments.length
özelliğiyle birlikte
arguments
dizisini kullanır:
function traceArgArray(x:int):void
{
for (var i:uint = 0; i < arguments.length; i++)
{
trace(arguments[i]);
}
}
traceArgArray(1, 2, 3);
// output:
// 1
// 2
// 3
arguments.callee
özelliği genellikle yineleme oluşturmak için adsız işlevlerde kullanılır. Kodunuza esneklik katmak için bunu kullanabilirsiniz. Yinelemeli işlevin adı, geliştirme döngünüzde değişirse, işlev adı yerine
arguments.callee
öğesini kullanmanız durumunda, işlev gövdenizde yinelemeli çağrıyı değiştirmekle ilgili endişe duymanız gerekmez. Yinelemeyi etkinleştirmek için, aşağıdaki işlev ifadesinde
arguments.callee
özelliği kullanılır:
var factorial:Function = function (x:uint)
{
if(x == 0)
{
return 1;
}
else
{
return (x * arguments.callee(x - 1));
}
}
trace(factorial(5)); // 120
İşlev bildiriminizde ... (rest) parametresini kullanırsanız,
arguments
nesnesini kullanamazsınız. Bunun yerine, parametreler için bildirdiğiniz parametre adlarını kullanarak parametrelere erişmeniz gerekir.
Ayrıca parametre adı olarak
"arguments"
dizesini kullanmaktan kaçınmalısınız, aksi takdirde bu,
arguments
nesnesini gölgeler. Örneğin, bir
arguments
parametresi eklenecek şekilde
traceArgArray()
işlevi yeniden yazılırsa, işlev gövdesinde
arguments
öğesine başvurular,
arguments
nesnesini değil, parametreyi ifade eder. Aşağıdaki kod herhangi bir çıktı oluşturmaz:
function traceArgArray(x:int, arguments:int):void
{
for (var i:uint = 0; i < arguments.length; i++)
{
trace(arguments[i]);
}
}
traceArgArray(1, 2, 3);
// no output
Önceki ActionScript sürümlerinde bulunan
arguments
nesnesi de geçerli işlevi çağıran işlevin başvurusu niteliğindeki
caller
adında bir özellik içerirdi.
caller
özelliği ActionScript 3.0'da yoktur ancak çağıran işleve başvuru gerekiyorsa, çağıran işlevi, başvurunun kendisi olan fazladan bir parametreyi iletecek şekilde değiştirebilirsiniz.
... (rest) parametresi
ActionScript 3.0, ... (rest) parametresi adında yeni bir parametre içerir. Bu parametre, virgül sınırlı herhangi bir sayıda argümanı kabul eden bir dizi parametresi belirtmenize olanak sağlar. Parametre, ayrılmış sözcükler dışında herhangi bir ada sahip olabilir. Bu parametre bildiriminin belirtilen son parametre olması gerekir. Bu parametrenin kullanılması,
arguments
nesnesini kullanılamaz duruma getirir. ... (rest) parametresi,
arguments
dizisi ve
arguments.length
özelliğiyle aynı işlevselliği verse de, bu,
arguments.callee
tarafından sağlanan işlevselliğe benzer bir işlevsellik sağlamaz. ... (rest) parametresini kullanmadan önce
arguments.callee
öğesini kullanmadığınızdan emin olmanız gerekir.
Aşağıdaki örnek,
arguments
nesnesi yerine ... (rest) parametresini kullanarak
traceArgArray()
işlevini yeniden yazar:
function traceArgArray(... args):void
{
for (var i:uint = 0; i < args.length; i++)
{
trace(args[i]);
}
}
traceArgArray(1, 2, 3);
// output:
// 1
// 2
// 3
... (rest) parametresi ayrıca listedeki son parametre olduğu sürece diğer parametrelerle de kullanılabilir. Aşağıdaki örnek, işlevin birinci parametresi (
x
) int türünde olacak ve ikinci parametre de ... (rest) parametresini kullanacak şekilde
traceArgArray()
işlevini değiştirir. Birinci parametre artık ... (rest) parametresi tarafından oluşturulan dizinin bölümü olmadığından, çıktı birinci değeri atlar.
function traceArgArray(x: int, ... args)
{
for (var i:uint = 0; i < args.length; i++)
{
trace(args[i]);
}
}
traceArgArray(1, 2, 3);
// output:
// 2
// 3
Nesne olarak işlevler
ActionScript 3.0'daki işlevler nesnelerdir. Bir işlev oluşturduğunuzda, yalnızca başka bir işleve parametre olarak iletilmekle kalmayan aynı zamanda kendisine eklenmiş özellik ve yöntemlerin de bulunduğu bir nesne oluşturursunuz.
Başka bir işleve argümanlar olarak iletilen işlevler, değere göre değil, başvuruya göre iletilir. Bir işlevi argüman olarak ilettiğinizde, yöntemi çağırmak için parantez operatörünü değil yalnızca tanımlayıcıyı kullanırsınız. Örneğin, aşağıdaki kod,
addEventListener()
yöntemine argüman olarak
clickListener()
adında bir işlev iletir:
addEventListener(MouseEvent.CLICK, clickListener);
ActionScript'i ilk defa kullanan programcılar için bu garip görünse de, işlevler tıpkı diğer nesneler gibi özelliklere ve yöntemlere sahip olabilir. Aslında, her işlev, kendisi için tanımlı parametrelerin sayısını saklayan
length
adında salt okunur bir özelliğe sahiptir. Bu, işleve gönderilen argümanların sayısını bildiren
arguments.length
özelliğinden farklıdır. ActionScript'te, bir işleve gönderilen argüman sayısının, o işlev için tanımlanmış parametre sayısını aşabileceğini unutmayın. Katı mod, iletilen argümanların sayısı ile tanımlanan parametrelerin sayısı arasında tam eşleşme gerektirdiğinden yalnızca standart modda derleme yapan aşağıdaki örnek, iki özellik arasındaki farkı gösterir:
// Compiles only in standard mode
function traceLength(x:uint, y:uint):void
{
trace("arguments received: " + arguments.length);
trace("arguments expected: " + traceLength.length);
}
traceLength(3, 5, 7, 11);
/* output:
arguments received: 4
arguments expected: 2 */
Standart modda, kendi işlev özelliklerinizi işlev gövdesinin dışında tanımlayabilirsiniz. İşlev özellikleri, işlevle ilgili bir değişkenin durumunu kaydetmenize olanak sağlayan yarı durağan özellikler görevi görebilir. Örneğin, belirli bir işlevin kaç defa çağrıldığını izlemek isteyebilirsiniz. Bir oyun yazıyorsanız ve bir kullanıcının belirli bir komutu kaç defa kullandığını izlemek istiyorsanız, statik sınıf özelliği kullanabilseniz de, bu işlevsellik kullanışlı olabilir. Katı mod, işlevlere dinamik özellikler eklemenize olanak sağlamadığından yalnızca standart modda derleme yapan aşağıdaki örnek, işlev bildirimi dışında bir işlev özelliği oluşturur ve işlev her çağrıldığında özelliği artırır:
// Compiles only in standard mode
var someFunction:Function = function ():void
{
someFunction.counter++;
}
someFunction.counter = 0;
someFunction();
someFunction();
trace(someFunction.counter); // 2
İşlev kapsamı
Bir işlevin kapsamı, yalnızca programın neresinde işlevin çağrılabileceğini değil, işlevin hangi tanımlara erişebildiğini de belirler. Değişken tanımlayıcıları için geçerli olan aynı kapsam kuralları, işlev tanımlayıcıları için de geçerlidir. Genel kapsamda bildirilen bir işlev, tüm kodunuzda kullanılabilir. Örneğin, ActionScript 3.0, kodunuzun herhangi bir yerinde kullanılabilir olan
isNaN()
ve
parseInt()
gibi genel işlevler içerir. Yuvalanmış bir işlev—başka bir işlev içinde bildirilen bir işlev—bildirildiği işlevin herhangi bir yerinde kullanılabilir.
Kapsam zinciri
Bir işlev her çalıştırılmaya başladığında, birçok nesne ve özellik oluşturulur. İlk olarak, işlev gövdesinde bildirilen parametreleri ve yerel değişkenleri veya işlevleri saklayan
etkinleştirme nesnesi
adında özel bir nesne oluşturulur. Etkinleştirme nesnesi dahili bir mekanizma olduğundan bu nesneye doğrudan erişemezsiniz. İkinci olarak, çalışma zamanının tanımlayıcı bildirimleri için denetleyeceği nesnelerin sıralanmış bir listesini içeren bir
kapsam zinciri
oluşturulur. Çalıştırılan her işlev, dahili bir özellikte saklanan bir kapsam zincirine sahiptir. Yuvalanmış bir işlev için, kapsam zinciri kendi etkinleştirme nesnesiyle başlar ve üst işlevinin etkinleştirme nesnesiyle devam eder. Zincir, genel nesneye ulaşıncaya kadar bu şekilde devam eder. Bir ActionScript programı başlatıldığında genel bir nesne oluşturulur ve bu nesne tüm genel değişkenleri ve işlevleri içerir.
İşlev kapanışları
İşlev kapanışı
, işlevin anlık görüntüsünü ve
sözlü ortamını
içeren bir nesnedir. İşlevin sözlü ortamı, işlevin değerleriyle birlikte kapsam zincirinde bulunan tüm değişkenleri, özellikleri, yöntemleri ve nesneleri içerir. Nesne veya sınıftan ayrı olarak bir işlev her çalıştırıldığında işlev kapanışları oluşturulur. İşlev kapanışlarının tanımlandıkları kapsamda bulunması, bir işlev farklı bir kapsama bir argüman veya bir döndürme değeri olarak iletildiğinde ilginç sonuçlar oluşturur.
Örneğin, aşağıdaki kod iki işlev oluşturur: bir dikdörtgenin alanını hesaplayan
rectArea()
adında yuvalanmış bir işlevi döndüren
foo()
ve
foo()
öğesini çağırıp döndürülen işlev kapanışını
myProduct
adında bir değişkende saklayan
bar()
.
bar()
işlevi, kendi
x
yerel değişkenini (2 değeriyle) tanımlasa da,
myProduct()
işlev kapanışı çağrıldığında bu,
foo() işlevinde tanımlı
x
değişkenini (40 değeriyle) içerir.
Bu nedenle de
bar()
işlevi,
8
değerini değil,
160
değerini döndürür.
function foo():Function
{
var x:int = 40;
function rectArea(y:int):int // function closure defined
{
return x * y
}
return rectArea;
}
function bar():void
{
var x:int = 2;
var y:int = 4;
var myProduct:Function = foo();
trace(myProduct(4)); // function closure called
}
bar(); // 160
Yöntemler, oluşturuldukları sözlü ortamla ilgili bilgi içermeleri yönünden benzer şekilde davranır. Bir yöntem, örneğinden ayıklanıp bağımlı bir yöntem oluşturduğunda bu özellik en belirgin durumda olur. İşlev kapanışı ile bağımlı yöntem arasındaki ana fark, bir işlev kapanışında
this
anahtar sözcüğünün değeri değişebilirken, bağımlı yöntemdeki
this
anahtar sözcüğünün değerinin her zaman başlangıçta eklendiği örneği ifade etmesidir.
|
|
|