Это из-за "цепочки областей видимости".В ActionScript 3 (который совместим с ECMAScript - JavaScript работает так же, как описано ниже), имеется встроенный список «мест», который используется для разрешения любой именованной переменной, называемой цепочкой областей действия.Например, когда в «нормальном» методе класса цепочка областей действия выглядит следующим образом:
- Текущий объект экземпляра (такой же, как
this
) - Объект класса (используется для доступа к статическим переменным)
- Глобальная область (используется для доступа к глобальным переменным, например,
Math
)
Но когда вы находитесь в анонимной внутренней функции, цепочка областей действия имеет однуЕще одна запись сверху, представляющая метод, который находился в области действия в тот момент, когда анонимная функция была создана .Например, предположим, что у вас есть этот код:
class C {
var membervar:int;
function f() {
var localvar:int;
var innerfunc:Function = function() {
// what is on the scopechain here?
};
innerfunc();
}
}
В этом случае, когда вы находитесь в строке, которая говорит «что здесь находится в scopechain», scopechain выглядит следующим образом (с первой областью видимостиниже будет первое место, которое будет проверено):
- Один экземпляр функции
f()
, с переменными localvar
и innerfunc
- Текущий экземпляр класса
C
- Класс
C
- Глобальная область действия
Важно понимать, что когда строка кода var innerfunc:Function = function()...
выполняется, она создаетФункция объекта на лету и настройка его цепочки видимости на лету.Например, предположим, что у вас есть этот (запутанный) код, который, учитывая аргумент an_arg
, возвращает функцию, которая при вызове выводит значение an_arg:
function f(an_arg:int):Function {
return function():void {
trace(an_arg);
}
}
Каждая функция, возвращаемаявызовы f()
имеют собственную цепочку областей видимости, указывающую на различные экземпляры f()
.Итак:
var func1:Function = f(3);
var func2:Function = f(4);
func1(); // prints 3
func2(); // prints 4
Распространенным способом избежать этой проблемы, если вы действительно хотите ссылаться на this
во внутренней функции, а не полагаться на магию цепочки областей видимости, является создание временной переменнойвызывается self
во внешней функции - в случае вашего примера кода это будет выглядеть так:
var self = this;
this.gallery.addEventListener(GalleryEvent.WHATEVER, function(event:*) {
// This works fine
self.gallery.someAction();
})
Я мог бы продолжать эту тему вечно - я нахожу это захватывающим :-)