Я думал, что имею достаточное представление об объекте this
в JavaScript. При работе с объектами, обратными вызовами, а также событиями и обработчиками у меня не было проблем с этим с незапамятных времен. Однако теперь все изменилось.
Я по уши влюбился в JavaScript. Чистый JS, то есть не jQuery, прототип.js, додзё... Поэтому, естественно, я стал использовать замыкания. Однако в некоторых случаях это
застает меня врасплох. Например, этот фрагмент:
function anyFunc(par)
{
//console.log(par);
console.log(this);
}
function makeClosure(func)
{
return function(par)
{
return func(par);
}
}
var close = makeClosure(anyFunc);
close('Foo');
var objWithClosure = {cls:makeClosure(anyFunc),prop:'foobar'};
objWithClosure.cls(objWithClosure.prop);
var scndObj = {prop:'Foobar2'};
scndObj.cls = makeClosure;
scndObj.cls = scndObj.cls(anyFunc);
scndObj.cls(scndObj.prop);
Во всех трех случаях this
регистрируется как объект окна.Это легко исправить, конечно:
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
Это исправление работает, я поместил его здесь, чтобы люди не отвечали на него, не объясняя, что мне нужно знать: почему это ведет себя так, как здесь?
гарантирует, что вызывающий объект фактически является объектом, которому принадлежит замыкание. Чего я не могу понять, так это:
Конечно же, this
указывает на объект окна в первом случае, но в других случаях этого не должно быть. Я попытался зарегистрировать this
в функции makeClosure непосредственно перед возвратом, и он зарегистрировал сам объект, а не объект window
. Но когда используется фактическое закрытие, this
возвращается к указанию на объект окна. Почему?
Единственное, о чем я могу думать, это то, что, передавая функцию anyFunc
в качестве аргумента, я на самом деле передаю window.anyFunc
. Итак, я попробовал это быстрое решение:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
С ожидаемыми результатами this
теперь указывает на объекты, но опять же: Почему? У меня есть несколько идей ( theFunc
является ссылкой на функцию в локальной области видимости [ this > private: theFunc
]?), но я уверен, что здесь есть люди с гораздо больше ноу-хау, когда дело доходит до JS, поэтому я надеялся получить от них больше объяснений или ссылок на статьи, которые стоит прочитать...
Спасибо
Обновление
Вот скрипка, может может быть, я что-то упустил, но здесь это регистрирует все виды вещей ;)
Edit/Update 2
Случай, который меня смущает, здесь.
Окончательное редактирование
Хорошо, пост получился довольно запутанным.Итак, чтобы уточнить: я ожидал поведения, подобного этому:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
Что меня зацепило, так это то, что функция anyFunc
не была объявлена в правильной области, и поэтому this
указывал на объект окна. Я узнал об этом, прочитав древний свиток, который нашел где-то в сети.
Но произошло нечто более сложное, поскольку объект функции, на который теперь ссылается globalVar, был создан со свойством [[scope]], ссылающимся на цепочку областей видимости, содержащую объект Activation/Variable, принадлежащий контексту выполнения, в котором он был созданный (и глобальный объект). Теперь объект Activation/Variable не может быть собран мусором, так как при выполнении объекта функции, на который ссылается globalVar, потребуется добавить всю цепочку областей действия из его свойства [[scope]] в область контекста выполнения, созданного для каждого вызова Это.
Итак, что мне нужно было сделать, так это упростить, а не усложнить вещи:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
Это должно работать, верно?
PS: Я исключаю ответ Алнитака, но особая благодарность Феликсу Клингу за терпение и информацию.