As
funções
são blocos de código que executam tarefas específicas e podem ser reutilizados no seu programa. Há dois tipos de funções no ActionScript 3.0:
métodos
e
fechamentos de função
. O fato de uma função ser uma chamada a um método ou um fechamento de função depende do contexto na qual ela é definida. Uma função é chamada de método quando é especificada como parte de uma definição de classe ou anexada a uma ocorrência de um objeto. Uma função é chamada de fechamento de função quando é definida de qualquer outra forma.
As funções sempre foram extremamente importantes no ActionScript. No ActionScript 1.0, por exemplo, a palavra-chave
class
não existir, por isso as "classes" eram definidas pelas funções do construtor. Embora a palavra-chave
class
tenha sido adicionada à linguagem, ainda é importante ter um bom entendimento das funções para aproveitar todas as vantagens que ela tem a oferecer. Isso pode ser um desafio para os programadores que esperam que as funções do ActionScript se comportem da mesma forma que as funções em linguagens como C++ ou Java. Embora a definição e a chamada de funções básicas não apresentem um desafio aos programadores experientes, alguns recursos mais avançados das funções do ActionScript exigem uma explicação.
Conceitos de funções básicas
Chamada de funções
Uma função é chamada usando seu identificador seguido de um operador parênteses (
()
). O operador parênteses delimita qualquer parâmetro de função que você deseja enviar para a função. Por exemplo, a função
trace()
é uma função de nível superior no ActionScript 3.0:
trace("Use trace to help debug your script");
Se estiver chamando uma função sem nenhum parâmetro, você deverá usar parênteses vazios. Por exemplo, você pode usar o método
Math.random()
, que não usa nenhum parâmetro, para gerar um número aleatório:
var randomNum:Number = Math.random();
Definição de suas próprias funções
Há duas maneiras de definir uma função no ActionScript 3.0: você pode usar uma instrução de função ou uma expressão de função. A escolha da técnica depende de sua preferência por um estilo de programação mais estático ou dinâmico. Defina suas funções com instruções de função se preferir uma programação de modo estático ou estrito. Defina as funções com expressões de função se tiver uma necessidade específica para isso. As expressões de função são usadas com mais freqüência em programação de modo dinâmico ou padrão.
Instruções de função
A instrução de função é a técnica preferida para definir funções no modo estrito. Uma instrução de função começa com a palavra-chave
function
e, em seguida, vem:
-
O nome da função
-
Os parâmetros, em uma lista delimitada por vírgula e entre parênteses
-
O corpo da função, ou seja, o código do ActionScript a ser executado quando a função é chamada, delimitado por chaves
Por exemplo, o código a seguir cria uma função que define um parâmetro e chama a função usando a sequência de caracteres "
hello"
como valor do parâmetro:
function traceParameter(aParam:String)
{
trace(aParam);
}
traceParameter("hello"); // hello
Expressões de função
A segunda forma de declarar uma função é usar uma instrução de atribuição com uma expressão de função, que às vezes também é chamada de literal de função ou função anônima. Este método é mais detalhado e amplamente usado nas versões anteriores do ActionScript.
Uma instrução de atribuição com uma expressão de função começa com a palavra-chave
var
e, em seguida, vem:
-
O nome da função
-
O operador dois-pontos (
:
)
-
A classe
Function
para indicar o tipo de dados
-
O operador de atribuição (
=
)
-
A palavra-chave
function
-
Os parâmetros, em uma lista delimitada por vírgula e entre parênteses
-
O corpo da função, ou seja, o código do ActionScript a ser executado quando a função é chamada, delimitado por chaves
Por exemplo, o seguinte código declara a função
traceParameter
usando uma expressão de função:
var traceParameter:Function = function (aParam:String)
{
trace(aParam);
};
traceParameter("hello"); // hello
Observe que um nome de função não é especificado da mesma forma que em uma instrução de função. Outra diferença importante entre a expressão de função e a instrução de função é que a primeira é uma expressão e não uma instrução. isso significa que uma expressão de função não é suficiente como uma instrução de função. Ela só pode ser usada como parte de uma instrução, em geral, de atribuição. O exemplo a seguir mostra uma expressão de função atribuída a um elemento de matriz:
var traceArray:Array = new Array();
traceArray[0] = function (aParam:String)
{
trace(aParam);
};
traceArray[0]("hello");
Escolha entre instruções e expressões
Como regra geral, use uma instrução de função a menos que circunstâncias específicas exijam o uso de uma expressão. As instruções de função são menos detalhadas e fornecem uma experiência mais consistente entre o modo estrito e o padrão do que as expressões de função.
As instruções de função são mais fáceis de ler do que as instruções de atribuição que contêm expressões de função. As instruções de função tornam o código mais conciso; elas são menos confusas do que as expressões de função, que requerem o uso das palavras-chave
var
e
function
.
As instruções de função fornecem uma experiência mais consistente entre os dois modos de compilação já que é possível usar a sintaxe de pontos nos modos estrito e padrão para chamar um método declarado usando uma instrução de função. Isso não é necessariamente verdadeiro para métodos declarados com uma expressão de função. Por exemplo, o código a seguir define uma classe chamada Example com dois métodos:
methodExpression()
, que é declarado com uma expressão de função, e
methodStatement()
, que é declarado com uma instrução de função. No modo estrito, não é possível usar a sintaxe de pontos para chamar o método
methodExpression()
.
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
As expressões de função são consideradas mais adequadas para a programação direcionada ao comportamento de tempo de execução ou dinâmico. Se preferir usar o modo estrito, mas também precisar chamar um método declarado com uma expressão de função, você poderá usar qualquer uma destas duas técnicas. Em primeiro lugar, você pode chamar o método usando colchetes (
[]
) em vez do operador ponto (
.
). A chamada de método a seguir é bem-sucedida nos modos estrito e padrão:
myExample["methodLiteral"]();
Em segundo lugar, você pode declarar a classe inteira como uma classe dinâmica. Embora isso permita chamar o método usando o operador dot, o lado negativo é que você sacrifica algumas funcionalidades do modo estrito para todas as ocorrências dessa classe. Por exemplo, o compilador não irá gerar um erro se você tentar acessar uma propriedade indefinida em uma ocorrência de uma classe dinâmica.
Há algumas circunstâncias nas quais as expressões de função são úteis. Um uso comum de expressões de função é para funções que são usadas uma única vez e, depois, são descartadas. Outro uso menos comum é para anexar uma função a uma propriedade de protótipo. Para obter mais informações, consulte Objeto de protótipo.
Há duas diferenças sutis entre as instruções de função e as expressões de função que devem ser levadas em conta ao escolher a técnica usada. A primeira diferença é que as expressões de função não existem independentemente como objetos em relação ao gerenciamento de memória e à coleta de lixo. Em outras palavras, durante a atribuição de uma expressão de função a outro objeto, como um elemento de matriz ou uma propriedade de objeto, você cria a única referência a essa expressão de função no código. Se a matriz ou o objeto ao qual a expressão de função é anexada sair do escopo ou não estiver disponível, não é mais possível acessar a expressão de função. Se a matriz ou o objeto forem excluídos, a memória usada pela expressão de função se torna qualificada para a coleta de lixo, o que significa que a memória é qualificada para ser reivindicada e reutilizada para outros fins.
O exemplo a seguir mostra que, para uma expressão de função, assim que a propriedade com a expressão atribuída for excluída, a função não ficará mais disponível. A classe Test é dinâmica, o que significa que é possível adicionar uma propriedade chamada
functionExp
que mantém uma expressão de função. A função
functionExp()
pode ser chamada com o operador dot, mas assim que a propriedade
functionExp
for excluída, a função ficará inacessível.
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
Se, no entanto, for definida com uma instrução de função, a função existirá como seu próprio objeto e continuará a existir mesmo depois que a propriedade à qual está anexada for excluída. O operador
delete
funciona apenas em propriedades de objetos, por isso até mesmo uma chamada para excluir a função
stateFunc()
em si não funciona.
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
A segunda diferença entre as instruções de função e as expressões de função é que as primeiras existem em todo o escopo no qual são definidas, incluindo em instruções que aparecem antes da instrução de função. As expressões de função, porém, são definidas somente para instruções subseqüentes. Por exemplo, o seguinte código chama com êxito a função
scopeTest()
antes que ela seja definida:
statementTest(); // statementTest
function statementTest():void
{
trace("statementTest");
}
As expressões de função não estão disponíveis antes de serem definidas, por isso o seguinte código resulta em um erro de tempo de execução:
expressionTest(); // run-time error
var expressionTest:Function = function ()
{
trace("expressionTest");
}
Retorno de valores de funções
Para retornar um valor de sua função, use a instrução
return
seguida pela expressão ou pelo valor literal que deseja retornar. Por exemplo, o seguinte código retorna uma expressão representando o parâmetro:
function doubleNum(baseNum:int):int
{
return (baseNum * 2);
}
Observe que a instrução
return
encerra a função, de forma que as instruções abaixo de uma instrução
return
não são executadas, como a seguir:
function doubleNum(baseNum:int):int {
return (baseNum * 2);
trace("after return"); // This trace statement will not be executed.
}
No modo estrito, você deve retornar um valor do tipo apropriado se decidir especificar um tipo de retorno. Por exemplo, o código a seguir gera um erro no modo estrito, porque não retorna um valor válido:
function doubleNum(baseNum:int):int
{
trace("after return");
}
Funções aninhadas
É possível aninhar funções, o que significa que as funções podem ser declaradas dentro de outras. Uma função aninhada está disponível apenas dentro da função pai, a menos que uma referência a ela seja transmitida ao código externo. Por exemplo, o seguinte código declara duas funções aninhadas dentro da função
getNameAndVersion()
:
function getNameAndVersion():String
{
function getVersion():String
{
return "10";
}
function getProductName():String
{
return "Flash Player";
}
return (getProductName() + " " + getVersion());
}
trace(getNameAndVersion()); // Flash Player 10
Quando funções aninhadas são transmitidas ao código externo, elas são transmitidas como fechamentos de função, o que significa que a função retém as definições que estão no escopo quando a função é definida. Para obter mais informações, consulte Escopo de funções.
Parâmetros de função
O ActionScript 3.0 fornece algumas funcionalidades para parâmetros de função que podem parecer novas aos programadores que não conhecem a linguagem. Embora a idéia de transmitir parâmetros por valor ou referência não deva ser nova para a maioria dos programadores, o objeto
arguments
e o parâmetro ... (rest) talvez sejam uma novidade para muitos.
Transmissão de argumentos por valor ou referência
Em muitas linguagens de programação, é importante entender a distinção entre transmitir argumentos por valor ou por referência, pois ela pode afetar a forma como o código é criado.
Ser transmitido por valor significa que o valor do argumento é copiado em uma variável local para uso dentro da função. Ser transmitido por referência significa que apenas uma referência ao argumento é transmitido, em vez do valor real. Não é feita nenhuma cópia do argumento real. Em vez disso, uma referência à variável transmitida como um argumento é criada e atribuída a uma variável local para uso dentro da função. Como uma referência a uma variável fora da função, a variável local fornece a capacidade de alterar o valor da variável original.
No ActionScript 3.0, todos os argumentos são transmitidos por referência, porque todos os valores são armazenados como objetos. Entretanto, os objetos que pertencem aos tipos de dados primitivos, que incluem Boolean, Number, int, uint e String, têm operadores especiais que fazem com que se comportem como se fossem transmitidos por valor. Por exemplo, o seguinte código cria uma função chamada
passPrimitives()
que define dois parâmetros chamados
xParam
e
yParam
, ambos do tipo int. Esses parâmetros são semelhantes às variáveis locais declaradas no corpo da função
passPrimitives()
. Quando a função for chamada com os argumentos
xValue
e
yValue
, os parâmetros
xParam
e
yParam
serão inicializados com referências aos objetos int representados por
xValue
e
yValue
. Como são primitivos, os argumentos se comportam como se fossem transmitidos por valor. Embora
xParam
e
yParam
inicialmente contenham apenas referências aos objetos
xValue
e
yValue
, quaisquer alterações às variáveis dentro do corpo da função gera novas cópias dos valores na memória.
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
Dentro da função
passPrimitives()
, os valores de
xParam
e
yParam
são incrementados, mas isso não afeta os valores de
xValue
e
yValue
, como mostra a última instrução
trace
. Isso seria válido mesmo que os parâmetros fossem nomeados de forma idêntica às variáveis,
xValue
e
yValue
, porque
xValue
e
yValue
dentro da função apontariam para novos locais na memória que existem separadamente das variáveis de mesmo nome fora da função.
Todos os outros objetos, ou seja, objetos que não pertencem aos tipos de dados primitivos, são transmitidos por referência, o que fornece a capacidade de alterar o valor das variáveis originais. Por exemplo, o código a seguir cria um objeto chamado
objVar
com duas propriedades,
x
e
y
. O objeto é transmitido como um argumento para a função
passByRef()
. Como não é de um tipo primitivo, o objeto não é apenas transmitido por referência, mas também permanece como uma. Isso significa que as alterações feitas aos parâmetros dentro da função afetam as propriedades do objeto fora da função.
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
O parâmetro
objParam
referencia o mesmo objeto que a variável global
objVar
. Como você pode ver nas instruções
trace
do exemplo, as alterações nas propriedades
x
e
y
do objeto
objParam
são refletidas no objeto
objVar
.
Valores de parâmetro padrão
No ActionScript 3.0, você pode declarar os
valores do parâmetro padrão
para uma função. Se uma chamada a uma função com valores de parâmetro padrão omitir um parâmetro com valores padrão, será usado o valor especificado na definição de função para esse parâmetro. Todos os parâmetros com valores padrão devem ser colocados no final da lista de parâmetros. Os valores atribuídos como padrão devem ser constantes de tempo de compilação. A existência de um valor padrão para um parâmetro efetivamente o torna um
parâmetro opcional
. Um parâmetro sem um valor padrão é considerado um
parâmetro necessário
.
Por exemplo, o seguinte código cria uma função com três parâmetros, dois dos quais têm valores padrão. Quando a função é chamada com apenas um parâmetro, os valores padrão para os parâmetros são usados.
function defaultValues(x:int, y:int = 3, z:int = 5):void
{
trace(x, y, z);
}
defaultValues(1); // 1 3 5
O objeto arguments
Quando os parâmetros forem transmitidos a uma função, será possível usar o objeto
arguments
para acessar informações sobre esses parâmetros. Alguns aspectos importantes do objeto
arguments
incluem o seguinte:
-
O objeto
arguments
é uma matriz que inclui todos os parâmetros transmitidos à função.
-
A propriedade
arguments.length
relata o número de argumentos transmitidos à função.
-
A propriedade
arguments.callee
fornece uma referência à função em si, que é útil para chamadas recursivas às expressões de função.
Nota:
O objeto
arguments
não estará disponível se qualquer parâmetro for chamado de
arguments
ou se for usado o parâmetro ... (rest).
Se o objeto
arguments
estiver referenciado no corpo de uma função, o ActionScript 3.0 permite que as chamadas de função incluam mais parâmetros do que os especificados na definição de função, mas gera um erro no compilador no modo restrito, se o número de parâmetros não corresponder ao número de parâmetros necessários (e, opcionalmente, quaisquer parâmetros opcionais). É possível usar o aspecto de matriz do objeto
arguments
para acessar qualquer parâmetro transmitido à função, independentemente de ele ser especificado na definição de função. O exemplo a seguir, que é compilado apenas no modo padrão, usa a matriz
arguments
com a propriedade
arguments.length
para rastrear todos os parâmetros transmitidos para a função
traceArgArray()
:
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
A propriedade
arguments.callee
, em geral, é usada em funções anônimas para criar recursão. Você pode usá-la para adicionar flexibilidade ao seu código. Se o nome de uma função recursiva for alterado durante o ciclo de desenvolvimento, não será necessário se preocupar em alterar a chamada recursiva no corpo da função se usar
arguments.callee
em vez do nome de função. A propriedade
arguments.callee
é usada na seguinte expressão de função para permitir recursão:
var factorial:Function = function (x:uint)
{
if(x == 0)
{
return 1;
}
else
{
return (x * arguments.callee(x - 1));
}
}
trace(factorial(5)); // 120
Caso você use o parâmetro ... (rest) na declaração de função, o objeto
arguments
não fica disponível. Em vez disso, você terá de acessar os parâmetros usando os nomes de parâmetro declarados para eles.
Você também deve ter o cuidado de evitar o uso da seqüência de caracteres
"arguments"
como parâmetro, porque ela obscurece o objeto
arguments
. Por exemplo, se a função
traceArgArray()
for reescrita de forma que um parâmetro
arguments
seja adicionado, as referências a
arguments
no corpo da função irão se referir ao parâmetro e não ao objeto
arguments
. O seguinte código não produz nenhuma saída:
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
O objeto
arguments
nas versões anteriores do ActionScript também continham uma propriedade chamada
caller
, que é uma referência á função que chamava a função atual. A propriedade
caller
não está presente no ActionScript 3.0, mas, se uma referência à função de chamada for necessária, você poderá alterar a função de chamada para que ela transmita um parâmetro extra que faça referência a si mesmo.
O parâmetro ... (rest)
O ActionScript 3.0 apresenta uma nova declaração de parâmetro chamada de parâmetro ... (rest). Esse parâmetro permite especificar um parâmetro de matriz que aceita uma grande quantidade de argumentos delimitados por vírgula. O parâmetro pode ter qualquer nome que não seja uma palavra reservada. Essa declaração de parâmetro deve ser o último parâmetro especificado. Usar este parâmetro torna o objeto
arguments
indisponível. Embora o parâmetro ... (rest) ofereça a mesma funcionalidade que a matriz
arguments
e a propriedade
arguments.length
, ele não fornece uma funcionalidade semelhante à fornecida por
arguments.callee
. Você deve se certificar de que não será preciso usar
arguments.callee
antes de usar o parâmetro ... (rest).
O exemplo a seguir reescreve a função
traceArgArray()
usando o parâmetro ... (rest) em vez do objeto
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
O parâmetro ... (rest) também pode ser usado com outros parâmetros, contanto que o último parâmetro seja listado. O exemplo a seguir modifica a função
traceArgArray()
para que seu primeiro parâmetro,
x
, seja do tipo int e o segundo use o parâmetro ... (rest). A saída ignora o primeiro valor, porque o primeiro parâmetro não faz mais parte da matriz criada pelo parâmetro ... (rest).
function traceArgArray(x: int, ... args)
{
for (var i:uint = 0; i < args.length; i++)
{
trace(args[i]);
}
}
traceArgArray(1, 2, 3);
// output:
// 2
// 3
Funções como objetos
As funções no ActionScript 3.0 são objetos. Durante a criação de uma função, você cria um objeto que não apenas pode ser transmitido como um parâmetro para outra função, mas também possui propriedades e métodos anexados.
As funções transmitidas como argumentos para outra função são transmitidas por referência e não por valor. Durante a transmissão de uma função como um argumento, é usado apenas o identificador e não o operador parênteses usado para chamar o método. Por exemplo, o código a seguir transmite uma função chamada
clickListener()
como um argumento para o método
addEventListener()
:
addEventListener(MouseEvent.CLICK, clickListener);
Embora possa parecer estranho aos programadores que não conhecem o ActionScript, as funções podem ter propriedades e métodos, assim como qualquer outro objeto. Na verdade, cada função possui uma propriedade somente leitura chamada
length
que armazena o número de parâmetros definido para a função. Isso é diferente na propriedade
arguments.length
, que relata o número de argumentos enviados à função. Lembre-se de que, no ActionScript, o número de argumentos enviados a uma função pode exceder o número de parâmetros definido para ela. O exemplo a seguir, que é compilado somente no modo padrão porque o modo estrito requer uma correspondência exata entre o número de argumentos transmitidos e o número de parâmetros definido, mostra a diferença entre as duas propriedades:
// 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 */
No modo padrão, é possível especificar suas próprias propriedades de função definindo-as fora do corpo da função. As propriedades de função podem servir como propriedades quase estáticas que permitem salvar o estado de uma variável relacionada à função. Por exemplo, você pode querer controlar o número de vezes que uma função específica é chamada. Essa funcionalidade pode ser útil quando você escreve um jogo e deseja controlar o número de vezes que um usuário usa um comando especifico, embora também seja possível usar uma propriedade de classe estática para isso. O exemplo a seguir, que é compilado somente no modo padrão porque o modo estrito não permite adicionar propriedades dinâmicas às funções, cria uma propriedade de função fora da declaração de função e incrementa a propriedade sempre que a função é chamada:
// Compiles only in standard mode
var someFunction:Function = function ():void
{
someFunction.counter++;
}
someFunction.counter = 0;
someFunction();
someFunction();
trace(someFunction.counter); // 2
Escopo da função
Um escopo de função determina não apenas o local em um programa no qual a função pode ser chamada, mas também as definições que ela pode acessar. As mesmas regras de escopo válidas para os identificadores de variável se aplicam aos identificadores de função. Uma função declarada no escopo global está disponível em todo o código. Por exemplo, o ActionScript 3.0 contém funções globais, tais como
isNaN()
e
parseInt()
, que estão disponíveis em qualquer lugar no seu código. Uma função aninhada (uma função declarada dentro de outra função) pode ser usada em qualquer lugar na função na qual ela foi declarada.
A cadeia do escopo
Sempre que uma função começa com a execução, vários objetos e propriedades são criados. Em primeiro lugar, é criado um objeto especial chamado
objeto de ativação
que armazena os parâmetros e quaisquer variáveis locais ou funções declaradas no corpo da função. Não é possível acessar o objeto de ativação diretamente, porque ele é um mecanismo interno. Em segundo lugar, é criada uma
cadeia do escopo
que contém uma lista ordenada de objetos em que o tempo de execução verifica as declarações de identificador. Cada função executada tem uma cadeia de escopo que é armazenada em uma propriedade interna. Para uma função aninhada, a cadeia do escopo começa com seu próprio objeto de ativação, seguido pelo objeto de ativação de sua função pai. A cadeia continua assim até atingir o objeto global. O objeto global é criado quando um programa do ActionScript começa e contém todas as variáveis e funções globais.
Fechamentos de função
Um
fechamento de função
é um objeto que contém um instantâneo de uma função e seu
ambiente léxico
. O ambiente léxico de uma função inclui todas as variáveis, propriedades, métodos e objetos na cadeia do escopo da função, além de seus valores. Os fechamentos de função são criados sempre que uma função é executada independentemente de um objeto ou uma classe. O fato de que os fechamentos de função mantêm o escopo no qual eles foram definidos cria resultados interessantes quando uma função é transmitida como um argumento ou um valor de retorno em um escopo diferente.
Por exemplo, o código a seguir cria duas funções:
foo()
, que retorna uma função aninhada chamada
rectArea()
que calcula a área de um retângulo, e
bar()
, que chama
foo()
e armazena o fechamento de função retornado em uma variável chamada
myProduct
. Muito embora a função
bar()
defina sua própria variável local
x
(com um valor 2), quando o fechamento de função
myProduct()
é chamado, ela mantém a variável
x
(com um valor 40) definida na função
foo().
A função
bar()
, portanto, retorna o valor
160
em vez de
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
Os métodos se comportam de forma semelhante pois também mantêm as informações sobre o ambiente léxico no qual são criados. Essa característica é a mais notável quando um método é extraído de sua ocorrência, que cria um método vinculado. A principal diferença entre um fechamento de função e um método vinculado é que o valor da palavra-chave
this
em um método vinculado sempre se refere à ocorrência à qual ele foi inicialmente anexado, enquanto que, em um fechamento de função, o valor da palavra-chave
this
pode ser alterado.
|
|
|