Замыкание в JavaScript и объект this

Я думал, что имею достаточное представление об объекте 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: Я исключаю ответ Алнитака, но особая благодарность Феликсу Клингу за терпение и информацию.

5
задан Elias Van Ootegem 31 July 2015 в 00:10
поделиться