Функции

Функциями называют блоки программного кода, выполняющие определенные задачи, которые можно повторно использовать в программах. В ActionScript 3.0 существует два типа функций: методы и закрытия функций . То, называется ли функция методом или закрытием функции, зависит от контекста, в котором определена эта функция. Функция называется методом, если она определяется как часть определения класса или прикрепляется к экземпляру объекта. Функция называется закрытием функции, если она определена каким-либо другим способом.

Функции всегда были очень важны в ActionScript. В ActionScript 1.0, например, ключевое слово class отсутствует, поэтому «классы» определялись функциями конструктора. Хотя ключевое слово class с тех пор и было добавлено к языку, четкое понимание функций по-прежнему важно, если требуется полностью использовать все преимущества, предлагаемые языком. Это, возможно, вызовет сложности у программистов, ожидающих, что функции ActionScript будут вести себя так же, как функции в языке C++ или Java. Хотя само определение основной функции и ее вызовов не должно представлять сложности для опытных программистов, некоторые более сложные возможности функций ActionScript требуют дополнительного объяснения.

Концепции основной функции

Вызов функций

При вызове функции с помощью ее идентификатора с указанием последующего оператора скобки ( () ). Оператор скобки используется для включения любых функциональных параметров, которые требуется передать функции. Например, функция trace() является функцией верхнего уровня в среде ActionScript 3.0:

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

Если вызывается функция без параметров, необходимо использовать пустые парные скобки. Например, можно использовать метод Math.random() , который не получает параметров, чтобы создавать произвольные числа.

var randomNum:Number = Math.random();

Определение собственных функций

В ActionScript 3.0 существует два способа определить функцию: можно использовать инструкцию function или выражение function. Выбираемая технология зависит от того, какой стиль программирования предпочтительнее: статический или динамический. Определите собственные функции с помощью инструкции function, если предпочтителен статический или строгий режим программирования. Определяйте свои функции с помощью выражения function, если в этом есть особая необходимость. Выражение function более часто используется в динамическом программировании или при использовании стандартного режима.

Инструкции Function

Инструкции Function являются предпочтительной методикой для определения функций в строгом режиме. Инструкция function начинается с ключевого слова function , за которым идут следующие элементы.

  • Имя функции

  • Заключенный в скобки список параметров, разделенных запятыми

  • Тело функции — это заключенный в фигурные скобки программный код ActionScript, который будет выполняться при вызове функции

Например, в следующем программном коде создается функция, определяющая параметр, а затем выполняется вызов этой функции с использованием строки "hello" в качестве значения параметра:

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

Выражения Function

Можно другим способом объявить функцию, используя инструкцию присваивания с выражением function. Этот метод иногда называется литералом функции или анонимной функцией. Это более трудоемкий метод, который широко использовался в ранних версиях ActionScript.

Инструкция присваивания с выражением функции начинается с ключевого слова var , за которым идут следующие элементы.

  • Имя функции

  • Оператор двоеточие ( : )

  • Класс Function для указания типа данных

  • Оператор присваивания ( = )

  • Ключевое слово function

  • Заключенный в скобки список параметров, разделенных запятыми

  • Тело функции — это заключенный в фигурные скобки программный код ActionScript, который будет выполняться при вызове функции

    Например, в следующем программном коде объявляется функция traceParameter , использующая выражение function.

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

    Обратите внимание, что в отличие от инструкции function имя функции не указывается. Другим важным отличием между выражениями function и инструкциями function является то, что выражение - это именно выражение, а не инструкция. Это означает, что выражение function не может использоваться отдельно подобно инструкции function. Выражение function может использоваться только в качестве части инструкции, обычно инструкции присваивания. В следующем примере показано выражение function, присвоенное элементу массива.

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

Выбор между инструкцией и выражением

Стандартное правило предписывает использовать инструкцию function до тех пор, пока в силу особых обстоятельств не потребуется использовать выражение. Инструкции function менее трудоемки и обеспечивают более согласованную работу в строгом и стандартном режиме, чем выражения function.

Инструкции function проще читаются чем инструкции присваивания, содержащие выражения function. Инструкции function делают код более кратким; они вносят меньше путаницы, чем выражения function, для которых требуется использовать оба ключевых слова: var и function .

Операторы function обеспечивают более согласованное поведение в обоих режимах компилятора, поскольку для вызова метода, объявленного с помощью оператора function, можно использовать синтаксис с точкой как в строгом, так и в стандартном режимах. Это не обязательно так для методов, объявленных с помощью выражения function. Например, в следующем программном коде определяется класс с именем Example, содержащий два метода: methodExpression() , объявляемый с помощью выражения function, а также метод methodStatement() , объявляемый с помощью инструкции function. В строгом режиме нельзя использовать синтаксис с точкой для вызова метода 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

Считается, что выражения function лучше подходят для программирования, в котором больше внимания уделяется поведению во время выполнения или динамическому поведению. Если предпочтительно использовать строгий режим, но также необходимо вызывать метод, объявленный с помощью выражения function, можно использовать одну из двух технологий. Во-первых, можно вызвать метод, используя квадратные скобки ( [] ) вместо оператора точки ( . ). Вызов следующего метода успешно выполняется как в строгом, так и в стандартном режимах.

myExample["methodLiteral"]();

Во-вторых, можно объявить весь класс динамическим. Хотя это позволит вызывать метод с помощью оператора точки, с другой стороны придется пожертвовать возможностью работы в строгом режиме со всеми экземплярами данного класса. Например, что компилятор не создает ошибку при попытке доступа к неопределенному свойству экземпляра динамического класса.

В некоторых обстоятельствах выражения могут быть очень полезны. Одним из наиболее распространенных случаев применения выражений function являются функции, которые используются однократно и потом сбрасываются. Другим менее частым вариантом применения является присоединение функции к свойству прототипа. Дополнительные сведения см. в разделе «Объект прототипа».

Существует два тонких различия между инструкциями function и выражениями function, которые следует учитывать при выборе методики использования. Первое отличие состоит в том, что выражения function не существуют независимо как объекты в отношении управления памятью и освобождения ресурсов. Говоря другими словами, если выражение function присваивается другому объекту, такому как элемент массива или свойство объекта, создается только ссылка на это выражение function в программном коде. Если этот элемент массива или объект, к которому прикрепляется выражение function, выходит из области действия или, говоря другими словами, больше недоступен, доступ к этому выражению function прекращается. Если этот элемент массива или объект удаляются, память, использовавшаяся выражением function, становится доступной для освобождения ресурсов, и это значит, что данную память можно затребовать и повторно использовать для других целей.

В следующем примере показано, что в выражении function, как только свойство, к которому присвоено выражение, удаляется, функция перестает быть доступной. Класс Test является динамическим, что означает, что можно добавить свойство с именем functionExp , в котором содержится выражение функции. Функции functionExp() могут вызываться с помощью оператора точки, но как только свойство functionExp удаляется, функция перестает быть доступной.

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

Но, с другой стороны, если функция вначале определяется с помощью инструкции function, то она существует как независимый объект и продолжает существовать даже после удаления свойства, к которому она прикреплена. Оператор delete работает только со свойствами объектов, поэтому даже запрос на удаление самой функции stateFunc() не срабатывает.

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

Второе различие между инструкциями function и выражениями function состоит в том, что инструкции function существуют во всей области действия, для которой они определены, в том числе и для инструкций, предшествовавших инструкции function. Выражения function, в отличие от этого, определяются только для последующих инструкций. Например, в следующем программном коде функция scopeTest() успешно вызывается до того, как она была определена.

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

Выражения function недоступны до тех пор, пока они не определены, поэтому возникает ошибка при выполнении следующего программного кода.

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

Возвращение значений из функций

Чтобы возвратить значение из функции, используйте инструкцию return с последующим указанием значения выражения или литерала, которое требуется вернуть. Например, в следующем программном коде возвращается выражение, отображающее этот параметр.

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

Обратите внимание, что оператор return прерывает выполнение функции, поэтому любые операторы, следующие за оператором return , выполняться не будут, как показано далее.

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

В строгом режиме необходимо, чтобы возвращалось значение соответствующего типа, если указан тип возвращаемого значения. Например, следующий программный код создает ошибку в строгом режиме, поскольку не возвращает действительное значение.

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

Вложенные функции

Можно выполнять вложение функций, это означает, что функции могут быть объявлены с другими функциями. Вложенная функция доступна только в рамках родительской функции до тех пор, пока ссылки на эту функцию передаются во внешний программный код. Например, в следующем программном коде объявляется две вложенных функции внутри функции getNameAndVersion() .

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

Если вложенные функции передаются во внешний программный код, они передаются как закрытия функций, и это означает, что функция сохраняет все определения, бывшие в области действия во время ее определения. Дополнительные сведения см. в разделе «Область действия функции».

Параметры функций

ActionScript 3.0 обеспечивает определенную функциональность для параметров функций, которые могут показаться нестандартными для программистов, мало знакомых с этим языком. Хотя идея передачи параметров значением или ссылкой должна быть знакома большинству программистов, объект arguments и параметр ... (rest) многим еще не знакомы.

Передача аргументов значением и ссылкой

Во многих языках программирования очень важно понимать различие между передачей аргументов значением или ссылкой; это различие может влиять на способ разработки программного кода.

Передача значением подразумевает, что значение аргумента копируется в локальную переменную для использования внутри функции. Передача ссылкой означает, что вместо фактического значения передается только ссылка на аргумент. Копирование фактического значения аргумента не выполняется. Вместо этого передается ссылка на переменную, поскольку аргумент создается и присваивается локальной переменной для использования внутри функции. Так как ссылка на переменную находится вне функции, локальная переменная дает возможность изменять значение исходной переменной.

В ActionScript 3.0 все аргументы передаются ссылками, поскольку все значения хранятся как объекты. Однако объекты, принадлежащие примитивным типам данных, к которым относятся Boolean, Number, int, uint, и String, имеют специальные операторы, которые позволяют воспроизвести поведение объектов при передаче аргументов значениями. Например, в следующем программном коде создается функция с именем passPrimitives() , определяющая два параметра с именем xParam и yParam , оба с типом int. Эти параметры сходны с локальными переменными, объявленными в теле функции passPrimitives() . Если функция вызывается с аргументами xValue и yValue , параметры xParam и yParam инициализируются со ссылками на объекты int, представленные значениями xValue и yValue . Поскольку эти аргументы имеют примитивные типы, они ведут себя так, как если бы передавались значениями. Хотя параметры xParam и yParam изначально содержат только ссылки на xValue и yValue объекты, любые изменения переменных в теле функции создают новые копии значений в памяти.

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() значения xParam и yParam являются инкрементальными, но это не влияет на значения xValue и yValue , как показано в последней инструкции trace . И это действительно будет так, даже если параметры будут названы так же, как переменные, xValue и yValue , поскольку имена xValue и yValue внутри функции будут указывать на новое местоположение в памяти, которое существует отдельно от переменных с таким же именем вне функции.

Все другие объекты, т.е объекты, которые не принадлежат примитивным типам данных, всегда передаются ссылками, что дает возможность изменять значение исходной переменной. Например, в следующем программном коде создается объект с именем objVar и двумя свойствами: x и y . Этот объект передается как аргумент функции passByRef() . Поскольку тип данных объекта не примитивный, он не только предается ссылкой, но также хранится как ссылка. Это означает, что изменения, вносимые в параметры в функции, влияют на свойства объекта вне функции.

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 ссылается на тот же объект, что и глобальная переменная objVar . Как можно видеть из инструкции trace в приведенном примере, изменения свойств x и y в объекте objParam отражаются в объекте objVar .

Значения параметров по умолчанию

В среде ActionScript 3.0 можно объявить значения параметров по умолчанию для функции. Если вызывается функция со значениями параметров по умолчанию, используются значения, указанные для параметров в определении функции. Все параметры со значениями по умолчанию должны быть помещены в конец списка параметров. Значения, которые присвоены в качестве значений по умолчанию, должны быть константами, определяемыми во время компиляции. Существование для параметра значения по умолчанию фактически делает этот параметр необязательным параметром . Параметр без значения по умолчанию считается обязательным параметром .

Например, в следующем программном коде создается функция с тремя параметрами, два из которых имеют значения по умолчанию. При вызове этой функции только с одним параметром используются значения для параметров по умолчанию.

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

Объект arguments

Если параметры передаются в функцию, можно использовать объект arguments для доступа к информации о параметрах, переданных функции. Наиболее важными для объекта arguments являются следующие аспекты.

  • Объект arguments является массивом, содержащим все параметры, переданные функции.

  • Свойство arguments.length сообщает о числе параметров, переданных функции.

  • Свойство arguments.callee передает ссылку на саму функцию, которая очень полезна при рекурсивных вызовах выражений function.

    Примечание. Объект arguments недоступен, если какой-либо параметр имеет имя arguments , а также в тех случаях, когда используется параметр ... (rest).

    Если в теле функции есть ссылки на объект arguments , ActionScript 3.0 позволяет включать в вызов функции больше параметров, чем указано в определении функции. Однако в строгом режиме будет выдаваться ошибка компиляции, если число переданных параметров не соответствует числу обязательных параметров (и дополнительных параметров, если такие имеются). Можно использовать этот аспект массива в объекте arguments для доступа к любому параметру, переданному функции, без учета того, был ли этот параметр задан в определении функции или нет. В следующем примере, который компилируется только в стандартном режиме, массив arguments со свойством arguments.length используется для отслеживания всех параметров, переданных в функцию 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

    Свойство arguments.callee часто используется в анонимных функциях для выполнения рекурсии. С ее помощью можно добавить гибкости создаваемому программному коду. Если имя рекурсивной функции изменяется в ходе цикла разработки, не следует беспокоиться об изменении рекурсивных вызовов в теле функции, если вместо имени функции используется свойство arguments.callee . Свойство arguments.callee используется в следующем выражении function для разрешения рекурсии.

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

    Если при объявлении функции используется параметр ... (rest), объект arguments недоступен. Вместо него необходимо будет обращаться к параметрам, используя объявленные для них имена.

    Необходимо соблюдать осторожность, чтобы избежать использования строки "arguments" в качестве имени параметра, поскольку из-за этого объект arguments может стать недоступным. Например, если функция traceArgArray() перезаписывается так, что добавляется параметр arguments , ссылка arguments в теле функции будет вызывать обращение параметру, а не к объекту arguments . В следующем программном коде не создается значений на выходе.

    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

    Объект arguments в предыдущих версиях ActionScript также содержал свойство с именем caller , которое является ссылкой на функцию, вызывающую текущую функцию. Свойство caller отсутствует в ActionScript 3.0, но если нужна ссылка на вызывающую функцию, можно изменить ее так, чтобы она передавала дополнительный параметр, являющейся ссылкой на нее саму.

Параметр ... (rest)

В ActionScript 3.0 появилось новая возможность объявления параметров, называемая параметр ... (rest). Этот параметр позволяет указать параметр массива, который принимает любое количество разделенных запятыми аргументов. Этот параметр может иметь любое имя при условии, что оно не является зарезервированным словом. Это объявление параметра должно быть последним указываемым параметром. Использование этого параметра делает объект arguments недоступным. Хотя параметр ... (rest) дает ту же функциональность, что массив arguments и свойство arguments.length , он не обеспечивает возможностей свойства arguments.callee . Необходимо убедиться, что использование возможностей свойства arguments.callee действительно не требуется, прежде чем использовать параметр ... (rest).

В следующем примере функция traceArgArray() перезаписывается с использованием параметра ... (rest) вместо объекта 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

Параметр ... (rest) также может использоваться с другими параметрами с условием, что он будет последним параметром в списке. В следующем примере функция traceArgArray() изменяется таким образом, что ее первый параметр, x , становится типом int, а второй — использует параметр ... (rest). При выводе первое значение пропускается, поскольку первый параметр больше не является частью массива, созданного параметром ... (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

Функции в качестве объектов

В ActionScript 3.0 функции являются объектами. При создании функции создается объект, который не только может передаваться как параметр другой функции, но также имеет свойства и методы, присоединенные к нему.

Функции передаются как аргументы другим функциям в виде ссылок, а не значений. Если функция передается как аргумент, используется только ее идентификатор, но не оператор скобки, применяемый для вызова метода. Например, в следующем программном коде функция с именем clickListener() передается как аргумент методу addEventListener() .

addEventListener(MouseEvent.CLICK, clickListener);

Хотя это может показаться странным для программистов, которые только начинают изучать ActionScript, как и любой другой объект, функции могут иметь свойства и методы. Действительно, каждая функция обладает доступным только для чтения свойством с именем length , в котором хранится число параметров, определенное для функции. Это свойство отличается от свойства arguments.length , в котором сообщалось о числе аргументов, переданных функции. Вспомним, что в ActionScript число аргументов, переданных функции, может превышать число параметров, заданных в определении этой функции. В следующем примере, который компилируется только в стандартном режиме, поскольку для строгого режима требуется точное соответствие числа переданных аргументов и параметров в определении, показано различие между этими двумя свойствами.

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

В стандартном режиме можно определить свои собственные свойства функции, поместив их определение вне тела создаваемой функции. Свойства функции могут выступать в роли квази-статических свойств, позволяя сохранять состояние переменной, связанной с данной функцией. Например, возможно, потребуется отследить, сколько раз вызывается определенная функция. Такая возможность может быть полезна, если пишется игра и требуется отследить, сколько раз пользователь применял определенную команду, хотя для этой цели вполне можно использовать и свойство статического класса. В следующем примере, компилируемом только в стандартном режиме, поскольку строгий режим не допускает добавления динамических свойств к функциям, создается свойство функции вне ее определения, а затем это свойство инкрементально увеличивается при каждом вызове функции.

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

Область действия функции

Область действия функции определяет не только, где в программе может вызываться функция, но также определения, которые доступны этой функции. Те же правила области действия, которые применимы к идентификаторам переменных, применяются и к идентификаторам функций. Функция, объявленная в глобальной области действия, доступна в любом месте программного кода. Например, ActionScript 3.0 содержит глобальные функции, такие как isNaN() и parseInt() , которые доступны в любом месте программного кода. Вложенная — это функция, объявленная внутри другой функции, которая может использоваться в любом месте функции, внутри которой она объявлена.

Цепочка области действия

Всякий раз, когда начинается выполнение функции, создается ряд объектов и свойств. Во-первых, создается специальный объект с названием объект активации , который хранит параметры и все локальные переменные или функции, объявленные в теле данной функции. Напрямую обратиться к объекту активации нельзя, поскольку это внутренний механизм. Во-вторых, создается цепочка области действия , содержащая упорядоченный список объектов, в которых среда выполнения проверяет объявления идентификаторов. Каждая выполняемая функция имеет цепочку области действия, хранимую во внутреннем свойстве. Для вложенных функций цепочка области действия начинается с собственного объекта активации, за которым следует объект активации родительской функции. Цепочка продолжается таким же образом, пока не будет достигнут глобальный объект. Глобальный объект создается при запуске программы ActionScript и содержит все глобальные переменные и функции.

Закрытия функций

Закрытие функции — это объект, содержащий моментальный снимок функции и ее лексическую среду . Лексическая среда функции включает все ее переменные, свойства, методы и объекты в цепочке области действия функции, а также их значения. Закрытие функции создается при каждом выполнении функции отдельно от объекта или класса. Тот факт, что закрытия функций удерживают области действия, в которых они были определены, дает интересные результаты, если функция передается в качестве аргумента или возвращаемого значения в другую область действия.

Например, в следующем программном коде создаются две функции: foo() , которая возвращает вложенную функцию с именем rectArea() , рассчитывающую площадь прямоугольника, и функцию bar() , вызывающую foo() и сохраняющую возвращаемое закрытие функции в переменной с именем myProduct . Несмотря на то, что функция bar() определяет свою собственную локальную переменную x (со значением 2), если вызывается закрытие функции myProduct() , она сохраняет переменную x (со значением 40), определенную в функции foo(). Функция bar() , таким образом, возвращает значение 160 вместо 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

Методы ведут себя сходным образом, они также сохраняют информацию о лексической среде, в которой они были созданы. Эта особенность наиболее заметна, если метод извлекается из своего экземпляра, создавая связанный метод. Главное отличие между закрытием функции и связанным методом состоит в том, что значение ключевого слова this в связанном методе всегда ссылается на экземпляр, к которому он был первоначально прикреплен, в то время как в закрытии функции значение ключевого слова this можно изменять.