Functies

Functies zijn blokken code die specifieke taken uitvoeren en opnieuw kunnen worden gebruikt in uw programma. Er zijn twee typen functies in ActionScript 3.0: methoden en functie closure . Of een functie een methode of functie closure wordt genoemd, hangt af van de context waarin de functie is gedefinieerd. Een functie wordt een methode genoemd als u deze definieert als onderdeel van een klassendefinitie of koppelt aan een instantie van een object. In alle andere gevallen is er sprake van een functie closure.

Functies hebben altijd een uiterst belangrijke rol gespeeld in ActionScript. In ActionScript 1.0 bestond het trefwoord class nog niet, zodat 'klassen' werden gedefinieerd met constructorfuncties. Hoewel het trefwoord class later in de taal is opgenomen, is een goed begrip van functies nog steeds belangrijk als u de taal optimaal wilt gebruiken. Dit kan een uitdaging vormen voor programmeurs die verwachten dat functies in ActionScript zich net zo gedragen als functies in talen zoals C++ of Java. Hoewel de basisbewerkingen voor het definiëren en aanroepen van functies voor ervaren programmeurs geen probleem hoeft te zijn, is voor sommige meer geavanceerde mogelijkheden van ActionScript enige uitleg vereist.

Elementaire functieconcepten

Functies aanroepen

U roept een functie aan door de id ervan te gebruiken, gevolgd door de ronde-haakjesoperator ( () ). Tussen de ronde haakjes plaatst u de functieparameters die u naar de functie wilt sturen. De functie trace() is bijvoorbeeld een functie op topniveau in ActionScript 3.0:

trace("Use trace to help debug your script");

Als u een functie aanroept zonder parameters, gebruikt u een leeg paar ronde haakjes. Met de methode Math.random() , waarvoor geen parameters worden gebruikt, genereert u bijvoorbeeld een willekeurig getal:

var randomNum:Number = Math.random();

Uw eigen functies definiëren

Er zijn twee manieren om een functie te definiëren in ActionScript 3.0: u kunt een functie-instructie of een functie-expressie gebruiken. De techniek die u kiest, hangt af van uw eigen voorkeur voor een meer statische of dynamische programmeerstijl. Definieer uw functies met functie-instructies als u de voorkeur geeft aan statisch programmeren (in de strikte modus). Definieer uw functies met functie-expressies als u daarvoor een specifieke reden hebt. Functie-expressies worden vaker gebruikt bij dynamisch programmeren (in de standaardmodus).

Functie-instructies

Functie-instructies genieten de voorkeur voor het definiëren van functies in de strikte modus. Een functie-instructie begint met het trefwoord function , gevolgd door:

  • De functienaam

  • De parameters, in een door komma's gescheiden lijst tussen ronde haakjes

  • De hoofdtekst van de functie, ofwel de ActionScript-code die wordt uitgevoerd bij het aanroepen van de functie, tussen accolades

Met de volgende code wordt bijvoorbeeld een functie gemaakt die een parameter definieert en wordt vervolgens de functie aangeroepen met de tekenreeks ' hello' als parameterwaarde:

function traceParameter(aParam:String) 
{ 
    trace(aParam); 
} 
 
traceParameter("hello"); // hello

Functie-expressies

De tweede manier om een functie te declareren is met behulp van een toewijzingsinstructie en een functie-expressie, ook wel een letterlijke functie of anonieme functie genoemd. Deze manier leidt tot uitgebreidere code en werd in eerdere versies van ActionScript veel gebruikt.

Een toewijzingsinstructie met een functie-expressie begint met het trefwoord var , gevolgd door:

  • De functienaam

  • De operator : (dubbele punt)

  • De klasse Function om het gegevenstype aan te duiden

  • De toewijzingsoperator ( = )

  • Het trefwoord function

  • De parameters, in een door komma's gescheiden lijst tussen ronde haakjes

  • De hoofdtekst van de functie, ofwel de ActionScript-code die wordt uitgevoerd bij het aanroepen van de functie, tussen accolades

    De volgende code declareert bijvoorbeeld de functie traceParameter met behulp van een functie-expressie:

    var traceParameter:Function = function (aParam:String) 
    { 
        trace(aParam); 
    }; 
    traceParameter("hello"); // hello

    Merk op dat u geen functienaam opgeeft, zoals bij een functie-instructie. Nog een belangrijk verschil is dat functie-expressies anders dan functie-instructies geen instructies zijn, maar expressies. Dit betekent dat een functie-expressie niet afzonderlijk kan bestaan en een functie-instructie wel. Een functie-expressie kan alleen als onderdeel van een instructie worden gebruikt, meestal een toewijzingsinstructie. In het volgende voorbeeld wordt een functie-expressie toegewezen aan een arrayelement:

    var traceArray:Array = new Array(); 
    traceArray[0] = function (aParam:String) 
    { 
        trace(aParam); 
    }; 
    traceArray[0]("hello");

Kiezen tussen instructies en expressies

Als algemene regel gebruikt u een functie-instructie tenzij specifieke omstandigheden het gebruik van een expressie vereisen. Functie-instructies zijn minder uitgebreid en zorgen voor meer consistentie bij het gebruik in zowel de strikte modus als de standaardmodus dan functie-expressies.

Functie-instructies zijn beter leesbaar dan toewijzingsinstructies met functie-expressies. Functie-instructies maken de code compacter en zijn minder verwarrend dan functie-expressies, waarbij u zowel het trefwoord var als function moet gebruiken.

Functie-instructies zorgen voor meer consistentie in de twee compilermodi. Zo kunt u de puntnotatie gebruiken in zowel de strikte modus als de standaardmodus om een methode aan te roepen die wordt gedeclareerd met een functie-instructie. Dit is niet altijd mogelijk voor methoden die worden gedeclareerd met een functie-expressie. Met de volgende code wordt bijvoorbeeld een klasse gedefinieerd met de naam Example met twee methoden: methodExpression() , gedeclareerd met een functie-expressie, en methodStatement() , gedeclareerd met een functie-instructie. In de strikte modus kunt u geen puntnotatie gebruiken om de methode methodExpression() aan te roepen.

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

Functie-expressies zijn over het algemeen beter geschikt voor programmeerdoeleinden die georiënteerd zijn op dynamisch gedrag bij uitvoering. Als u in de strikte modus wilt werken maar ook een methode moet aanroepen die wordt gedeclareerd met een functie-expressie, kunt u een van de volgende twee technieken toepassen. Met de eerste techniek roept u de methode aan met behulp van vierkante haakjes ( [] ) in plaats van de puntoperator ( . ). De volgende methodeaanroep is mogelijk in zowel de strikte modus als de standaardmodus:

myExample["methodLiteral"]();

Met de tweede techniek declareert u de gehele klasse als dynamische klasse. Hoewel u de methode zo wel kunt aanroepen met de puntoperator, gaat dit ten koste van enige functionaliteit van de strikte modus voor alle instanties van die klasse. De compiler genereert bijvoorbeeld geen fout wanneer u toegang probeert te krijgen tot een ongedefinieerde eigenschap voor een instantie van een dynamische klasse.

Er zijn enkele omstandigheden waarin functie-expressies nuttig zijn. Functie-expressies worden vaak gebruikt voor functies die maar eenmalig worden toegepast. Minder vaak worden ze gebruikt om een functie te koppelen aan een prototype-eigenschap. Zie Prototypeobject voor meer informatie.

Er zijn twee subtiele verschillen tussen functie-instructies en functie-expressies waarmee u rekening moet houden wanneer u kiest welke techniek u gebruikt. Het eerste verschil is dat functie-expressies niet als onafhankelijke objecten bestaan met betrekking tot geheugenbeheer en opschonen. Met andere woorden, wanneer u een functie-expressie toewijst aan een ander object, zoals een arrayelement of een objecteigenschap, maakt u de enige verwijzing naar die functie in de code. Als de array of het object waaraan de functie-expressie is gekoppeld buiten het bereik valt of om een andere reden niet meer beschikbaar is, hebt u geen toegang meer tot de functie-expressie. Als de array of het object wordt verwijderd, komt het geheugen van de functie-expressie in aanmerking voor opschonen ofwel beschikbaar voor andere doeleinden.

Het volgende voorbeeld laat zien dat voor een functie-expressie na het verwijderen van de eigenschap waaraan de expressie is toegewezen, de functie niet meer beschikbaar is. De klasse Test is van het type dynamic, wat betekent dat u een eigenschap met de naam functionExp kunt toevoegen met een functie-expressie. De functie functionExp() kan worden aangeroepen met de puntoperator, maar nadat de eigenschap functionExp is verwijderd, is de functie niet meer beschikbaar.

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

Als de functie eerst wordt gedefinieerd met een functie-instructie, bestaat deze als een eigen object, ook als de eigenschap wordt verwijderd waaraan de functie is gekoppeld. De operator delete werkt alleen voor eigenschappen van objecten. Een aanroep om de functie stateFunc() zelf te verwijderen, werkt dus niet.

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

Het tweede verschil tussen functie-instructies en functie-expressies is dat functie-instructies bestaan in het gehele bereik waarin ze worden gedefinieerd, ook in instructies die vóór de functie-instructie staan. Functie-expressies daarentegen worden alleen gedefinieerd voor daaropvolgende instructies. In de volgende code wordt de functie scopeTest() bijvoorbeeld aangeroepen voordat deze is gedefinieerd:

statementTest(); // statementTest 
 
function statementTest():void 
{ 
    trace("statementTest"); 
}

Functie-expressies zijn niet beschikbaar voordat ze worden gedefinieerd. De volgende code resulteert dan ook in een uitvoeringsfout:

expressionTest(); // run-time error 
 
var expressionTest:Function = function () 
{ 
    trace("expressionTest"); 
}

Waarden retourneren uit functies

Als u een waarde wilt retourneren uit een functie, gebruikt u de instructie return gevolgd door de expressie of letterlijke waarde die u wilt laten retourneren. De volgende code retourneert bijvoorbeeld een expressie die de parameter vertegenwoordigt:

function doubleNum(baseNum:int):int 
{ 
    return (baseNum * 2); 
}

U ziet dat de instructie return de functie beëindigt, zodat instructies onder een instructie return niet worden uitgevoerd:

function doubleNum(baseNum:int):int { 
    return (baseNum * 2); 
    trace("after return"); // This trace statement will not be executed. 
}

In de strikte modus moet u een waarde van het geschikte type retourneren als u ervoor kiest een retourneringstype op te geven. De volgende code genereert bijvoorbeeld een fout in de strikte modus, omdat geen geldige waarde wordt geretourneerd:

function doubleNum(baseNum:int):int 
{ 
    trace("after return"); 
}

Geneste functies

U kunt functies nesten, wat betekent dat u functies kunt declareren binnen andere functies. Een geneste functie is alleen beschikbaar binnen de bovenliggende functie, tenzij een verwijzing naar de functie wordt doorgegeven naar externe code. De volgende code declareert bijvoorbeeld twee geneste functies binnen de functie getNameAndVersion() :

function getNameAndVersion():String 
{ 
    function getVersion():String 
    { 
        return "10"; 
    } 
    function getProductName():String 
    { 
        return "Flash Player"; 
    } 
    return (getProductName() + " " + getVersion()); 
} 
trace(getNameAndVersion()); // Flash Player 10

Wanneer geneste functies worden doorgegeven aan externe code, gebeurt dit als een functie closure. Dit betekent dat de functie de definities behoudt die binnen het bereik vallen wanneer de functie wordt gedefinieerd. Zie Functiebereik voor meer informatie.

Functieparameters

ActionScript 3.0 biedt enige functionaliteit voor functieparameters die mogelijk nieuw lijkt voor programmeurs zonder ervaring in deze taal. Hoewel het idee van parameters doorgeven als waarde of als verwijzing bij de meeste programmeurs bekend zal zijn, geldt dat mogelijk niet voor het object arguments en de parameter ... (rest).

Argumenten doorgeven als waarde of als verwijzing

In veel programmeertalen is het van belang het onderscheid te weten tussen het doorgeven van argumenten als waarde of als verwijzing. Dit onderscheid kan van invloed zijn op de wijze waarop code wordt samengesteld.

Doorgeven als waarde betekent dat de waarde van het argument wordt gekopieerd naar een lokale variabele om in de functie te gebruiken. Doorgeven als verwijzing betekent dat alleen een verwijzing naar het argument wordt doorgegeven en niet de feitelijke waarde. Er wordt geen kopie van het eigenlijke argument gemaakt. In plaats daarvan wordt een verwijzing naar de variabele doorgegeven als een argument wordt gemaakt en toegewezen aan een lokale variabele voor gebruik in de functie. Als verwijzing naar een variabele buiten de functie geeft de lokale variabele u de mogelijkheid om de waarde van de oorspronkelijke variabele te wijzigen.

In ActionScript 3.0 worden alle argumenten doorgegeven als verwijzing, omdat alle waarden als objecten worden opgeslagen. Objecten die behoren tot de primitieve gegevenstypen (Boolean, Number, int, uint en String) hebben speciale operatoren waardoor ze gedrag vertonen alsof ze als waarde zijn doorgegeven. Met de volgende code wordt bijvoorbeeld een functie gemaakt met de naam passPrimitives() die twee parameters definieert met de naam xParam en yParam , beide van het type int. Deze parameters lijken op lokale variabelen die worden gedeclareerd in de hoofdtekst van de functie passPrimitives() . Wanneer de functie wordt aangeroepen met de argumenten xValue en yValue , worden de parameters xParam en yParam geïnitialiseerd met verwijzingen naar de objecten int vertegenwoordigd door xValue en yValue . Omdat de argumenten primitieven zijn, gedragen deze zich alsof ze als waarde zijn doorgegeven. Hoewel xParam en yParam eerst alleen verwijzingen bevatten naar de objecten xValue en yValue , genereren wijzigingen in de variabelen in de hoofdtekst van de functie nieuwe kopieën van de waarden in het geheugen.

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

Binnen de functie passPrimitives() worden de waarden van xParam en yParam verhoogd. Dit heeft echter geen invloed op de waarden van xValue en yValue , zoals wordt getoond in de laatste instructie trace . Dit geldt ook als de parameters dezelfde naam zouden hebben als de variabelen, xValue en yValue , omdat de xValue en yValue binnen de functie naar nieuwe locaties in het geheugen zouden wijzen die afzonderlijk bestaan van de variabelen met dezelfde naam buiten de functie.

Alle andere objecten (die niet behoren tot de primitieve gegevenstypen) worden altijd doorgegeven als verwijzing. Dit maakt het mogelijk de waarde van de oorspronkelijke variabele te wijzigen. Met de volgende code wordt bijvoorbeeld een object gemaakt met de naam objVar met twee eigenschappen: x en y . Het object wordt als argument aan de functie passByRef() doorgegeven. Aangezien het object geen primitief type is, wordt het object niet alleen als verwijzing doorgegeven, maar blijft het ook een verwijzing. Dit betekent dat wijzigingen in parameters binnen de functie van invloed zijn op de objecteigenschappen buiten de functie.

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

De parameter objParam verwijst naar hetzelfde object als de algemene variabele objVar . Zoals u kunt zien in de instructies trace in het voorbeeld, worden wijzigingen in de eigenschappen x en y van het object objParam weergegeven in het object objVar .

Standaardparameterwaarden

In ActionScript 3.0 kunt u voor een functie standaardparameterwaarden declareren. Als bij het aanroepen van een functie met standaardparameterwaarden een parameter met standaardwaarden wordt weggelaten, wordt de opgegeven waarde in de functiedefinitie voor die parameter gebruikt. Alle parameters met standaardwaarden moeten aan het eind van de lijst met parameters worden geplaatst. De toegewezen standaardwaarden moeten constanten bij compileren zijn. Het bestaan van een standaardwaarde voor een parameter maakt van die parameter feitelijk een optionele parameter . Een parameter zonder standaardwaarde wordt als vereiste parameter beschouwd.

Met de volgende code wordt bijvoorbeeld een functie met drie parameters gemaakt, waarvan er twee een standaardwaarde hebben. Wanneer de functie wordt aangeroepen met slechts één parameter, worden de standaardwaarden voor de parameters gebruikt.

function defaultValues(x:int, y:int = 3, z:int = 5):void 
{ 
    trace(x, y, z); 
} 
defaultValues(1); // 1 3 5

Het object arguments

Wanneer parameters worden doorgegeven aan een functie, kunt u het object arguments gebruiken voor toegang tot informatie over de parameters die aan de functie worden doorgegeven. Sommige belangrijke aspecten van het object arguments zijn onder meer:

  • Het object arguments is een array met alle parameters die aan de functie worden doorgegeven.

  • De eigenschap arguments.length rapporteert het aantal parameters dat aan de functie wordt doorgegeven.

  • De eigenschap arguments.callee zorgt voor een verwijzing naar de functie zelf, wat nuttig is voor recursieve aanroepen van functie-expressies.

    Opmerking: Het object arguments is niet beschikbaar als een parameter de naam arguments heeft of als u de parameter ... (rest) gebruikt.

    Als vanuit het hoofdgedeelte van een functie wordt verwezen naar het object arguments , kunnen functieoproepen in ActionScript 3.0 meer parameters bevatten dan in de functiedefinitie zijn gedefinieerd. In de strikte modus wordt echter een compilatiefout gegenereerd als het aantal parameters niet overeenkomt met het aantal vereiste parameters (en desgewenst eventuele optionele parameters). U kunt het arrayaspect van het object arguments gebruiken voor toegang tot parameters die aan de functie worden doorgegeven, of de parameter nu is gedefinieerd in de functiedefinitie of niet. In het volgende voorbeeld, dat alleen in de standaardmodus kan worden gecompileerd, wordt de array arguments gebruikt samen met de eigenschap arguments.length om alle parameters te traceren die aan de functie traceArgArray() worden doorgegeven:

    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

    De eigenschap arguments.callee wordt vaak gebruikt in anonieme functies om herhaling te bewerkstelligen. U kunt daarmee flexibiliteit toevoegen aan uw code. Als de naam van een recursieve functie verandert gedurende de ontwikkelingscyclus, hoeft u zich geen zorgen te maken om de recursieve aanroep in de hoofdtekst van de functie te wijzigen als u arguments.callee gebruikt in plaats van de functienaam. De eigenschap arguments.callee wordt gebruikt in de volgende functie om herhaling mogelijk te maken:

    var factorial:Function = function (x:uint) 
    { 
        if(x == 0) 
        { 
            return 1; 
        } 
        else 
        { 
            return (x * arguments.callee(x - 1)); 
        } 
    } 
     
    trace(factorial(5)); // 120

    Als u de parameter ... (rest) gebruikt in uw functiedeclaratie, is het object arguments voor u niet beschikbaar. In plaats daarvan hebt u toegang tot de parameters met de parameternamen die u daarvoor declareert.

    Zorg er ook voor dat u de tekenreeks 'arguments' niet gebruikt als parameternaam, wat als schaduw van het object arguments zou werken. Als de functie traceArgArray() bijvoorbeeld wordt herschreven zodat een parameter arguments wordt toegevoegd, verwijzen de verwijzingen naar arguments in de hoofdtekst van de functie naar de parameter in plaats van naar het object arguments . De volgende code produceert geen uitvoer:

    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

    Het object arguments in eerdere versies van ActionScript bevatte ook een eigenschap met de naam caller , ofwel een verwijzing naar de functie die de huidige functie aanroept. De eigenschap caller wordt niet meer gebruikt in ActionScript 3.0. Als u echter moet verwijzen naar de aanroepende functie, kunt u de aanroepende functie een extra parameter laten doorgeven als verwijzing naar de functie zelf.

De parameter ... (rest)

ActionScript 3.0 introduceert een nieuwe parameterdeclaratie: de parameter ... (rest). Met deze parameter kunt u een arrayparameter opgeven die een willekeurig aantal door komma's gescheiden argumenten accepteert. De parameter kan elke naam hebben die geen gereserveerd woord is. Deze parameterdeclaratie moet de laatste parameter zijn die wordt opgegeven. Wanneer u deze parameter gebruikt, is het object arguments niet beschikbaar. Hoewel de parameter ... (rest) dezelfde functionaliteit biedt als de array arguments en de eigenschap arguments.length , ontbreekt de functionaliteit die arguments.callee biedt. U moet ervoor zorgen dat u arguments.callee niet hoeft te gebruiken voordat u de parameter ... (rest) gebruikt.

In het volgende voorbeeld wordt de functie traceArgArray() herschreven met de parameter ... (rest) in plaats van het object arguments :

function traceArgArray(... args):void 
{ 
    for (var i:uint = 0; i < args.length; i++) 
    { 
        trace(args[i]); 
    } 
} 
 
traceArgArray(1, 2, 3); 
 
// output: 
// 1 
// 2 
// 3

U kunt de parameter ... (rest) (als laatste parameter) ook gebruiken met andere parameters. In het volgende voorbeeld wordt de functie traceArgArray() zo gewijzigd dat de eerste parameter, x , van het type int is en de tweede parameter de parameter ... (rest) gebruikt. Bij de uitvoer wordt de eerste waarde overgeslagen, omdat de eerste parameter geen onderdeel meer vormt van de array die met de parameter ... (rest) wordt gemaakt.

function traceArgArray(x: int, ... args) 
{ 
    for (var i:uint = 0; i < args.length; i++) 
    { 
        trace(args[i]); 
    } 
} 
 
traceArgArray(1, 2, 3); 
 
// output: 
// 2 
// 3

Functies als objecten

Functies in ActionScript 3.0 zijn objecten. Wanneer u een functie maakt, maakt u een object dat als parameter aan een andere functie kan worden doorgegeven én waaraan eigenschappen en methoden kunnen worden gekoppeld.

Het doorgeven van functies als argumenten aan een andere functie gebeurt als verwijzing en niet als waarde. Wanneer u een functie doorgeeft als argument, gebruikt u alleen de id en niet de ronde-haakjesoperator waarmee u de methode aanroept. In de volgende code wordt bijvoorbeeld een functie met de naam clickListener() doorgegeven als argument aan de methode addEventListener() :

addEventListener(MouseEvent.CLICK, clickListener);

Hoewel dit voor programmeurs zonder ervaring in ActionScript wat vreemd kan lijken, kunnen functies eigenschappen en methoden hebben, net als andere objecten. In feite heeft elke functie een alleen-lezen eigenschap met de naam length waarin het aantal gedefinieerde parameters voor de functie wordt opgeslagen. Dit verschilt van de eigenschap arguments.length , die het aantal argumenten aangeeft dat aan de functie wordt doorgegeven. Zoals al eerder is opgemerkt, kan in ActionScript het aantal doorgegeven argumenten aan een functie hoger zijn dan het aantal gedefinieerde parameters voor die functie. In het volgende voorbeeld wordt het verschil getoond tussen de twee eigenschappen (compilatie kan alleen in de standaardmodus, omdat voor de strikte modus is vereist dat het aantal doorgegeven argumenten en het aantal gedefinieerde parameters exact gelijk zijn):

// 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 */

In de standaardmodus kunt u uw eigen functie-eigenschappen definiëren buiten de hoofdtekst van de functie. U kunt functie-eigenschappen als quasi-statische eigenschappen gebruiken, zodat u de status van een variabele in relatie tot de functie kunt opslaan. U wilt bijvoorbeeld het aantal keren bijhouden dat een bepaalde functie wordt aangeroepen. Een dergelijke functionaliteit kan nuttig zijn als u een spel ontwikkelt en wilt bijhouden hoe vaak een gebruiker een bepaalde opdracht gebruikt, hoewel u daar ook een statische klasseneigenschap voor kunt gebruiken. Met de volgende code wordt een functie-eigenschap gemaakt buiten de functiedeclaratie en wordt de eigenschap verhoogd telkens wanneer de functie wordt aangeroepen. Dit voorbeeld kan alleen worden gecompileerd in de standaardmodus omdat het in de strikte modus niet mogelijk is dynamische eigenschappen toe te voegen aan functies.

// Compiles only in standard mode 
var someFunction:Function = function ():void 
{ 
    someFunction.counter++; 
} 
 
someFunction.counter = 0; 
 
someFunction(); 
someFunction(); 
trace(someFunction.counter); // 2

Functiebereik

Het bereik van een functie bepaalt waar in een programma die functie kan worden aangeroepen en tot welke definities de functie toegang heeft. Dezelfde bereikregels die gelden voor variabele-id's gelden ook voor functie-id's. Een functie die wordt gedeclareerd in het algemene bereik, is in de gehele code beschikbaar. ActionScript 3.0 bevat bijvoorbeeld algemene functies, zoals isNaN() en parseInt() , die overal in de code beschikbaar zijn. Een geneste functie (gedeclareerd binnen een andere functie) kan overal in de functie worden gebruikt waarin het is gedeclareerd.

De bereikketen

Aan het begin wanneer een functie wordt uitgevoerd, wordt een aantal objecten en eigenschappen gemaakt. Eerst wordt een speciaal activeringsobject gemaakt met de parameters en de lokale variabelen of functies die in de hoofdtekst van de functie zijn gedeclareerd. U hebt geen directe toegang tot het activeringsobject, omdat het een intern mechanisme betreft. Vervolgens wordt een bereikketen gemaakt met een geordende lijst met objecten die tijdens de uitvoering wordt gecontroleerd op id-declaraties. Elke uitgevoerde functie heeft een bereikketen die in een interne eigenschap wordt opgeslagen. Voor een geneste functie begint de bereikketen met het eigen activeringsobject, gevolgd door het activeringsobject van de bovenliggende functie. De keten gaat op deze wijze verder tot het algemene object is bereikt. Het algemene object wordt gemaakt wanneer een ActionScript-programma begint en dit object bevat alle algemene variabelen en functies.

Functie closure

Een functie closure is een object met een momentopname van een functie en de bijbehorende lexicale omgeving . De lexicale omgeving van een functie omvat alle variabelen, eigenschappen, methoden en objecten in de bereikketen van de functie, samen met de waarden ervan. Een functie closure wordt gemaakt telkens wanneer een functie wordt uitgevoerd apart van een object of een klasse. Het feit dat een functie closure het bereik behoudt waarin deze is gedefinieerd, levert interessante resultaten op wanneer een functie als argument of geretourneerde waarde in een ander bereik wordt doorgegeven.

Met de volgende code worden bijvoorbeeld twee functies gemaakt: foo() , die een geneste functie retourneert met de naam rectArea() waarmee de oppervlakte van een rechthoek wordt berekend, en bar() , die foo() aanroept en de geretourneerde functie closure opslaat in een variabele met de naam myProduct . Ook al definieert de functie bar() de eigen lokale variabele x (met een waarde van 2), wordt bij het aanroepen van de functie closure myProduct() de variabele x behouden (met een waarde van 40) die is gedefinieerd in de functie foo(). De functie bar() retourneert dan ook de waarde 160 in plaats van 8 .

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

Methoden vertonen hetzelfde gedrag wat betreft het behouden van informatie over de lexicale omgeving waarin ze zijn gemaakt. Dit valt het meest op wanneer een methode wordt geëxtraheerd uit de instantie ervan, wat resulteert in een gebonden methode. Het belangrijkste verschil tussen een functie closure en een gebonden methode is dat de waarde van het trefwoord this in een gebonden methode altijd verwijst naar de instantie waaraan deze eerst was gekoppeld, terwijl in een functie closure de waarde van het trefwoord this kan veranderen.