JavaScript闭包和这个对象

Eli*_*gem 5 javascript closures object this

我以为我对thisJavaScript 中的对象有了合理的理解.在处理对象,回调以及事件和处理程序时,我从远古时代就没有遇到过任何问题.然而,现在一切都发生了变化.

爱上了JavaScript,我已经爱不释手了.纯JS,也就是说,不是jQuery,prototype.js,dojo ......当然,我已经开始使用闭包了.但在某些情况下,this让我措手不及.把这个片段拿一个:

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);
Run Code Online (Sandbox Code Playgroud)

在所有三种情况下,this日志都作为窗口对象.当然,这是一个简单的解决方法:

function makeClosure(func)
{
    return function(par)
    {
        return func.call(this,par);
    }
}
Run Code Online (Sandbox Code Playgroud)

这个修复工作,我把它放在这里,以避免人们回答这个问题,而不解释我需要知道的事情:为什么这样做会像在这里一样?

确保调用者实际上是闭包属于的对象.我不明白的是:this在第一种情况下,指向窗口对象,但在其他情况下,它不应该.我this在返回之前尝试登录makeClosure函数,它确实记录了对象本身,而不是window对象.但是当使用实际的闭包时,this返回指向窗口对象.为什么?

我唯一能想到的是,通过将anyFunc函数作为参数传递,我实际上是在传递window.anyFunc.所以我尝试了这个快速修复:

function makeClosure(func)
{
    var theFunc = func;
    return function(par)
    {
        theFunc(par);
    }
}
Run Code Online (Sandbox Code Playgroud)

有了预期的结果,this现在指向对象,但又一次:为什么?我有一些想法(theFunc是对本地范围[ this > private: theFunc]中的函数的引用?),但我确信这里有人在JS方面有更多的技术诀窍,所以我希望得到一些更多解释或链接到值得他们阅读的文章......

谢谢

更新

这是一个小提琴,可能是我留下了一些东西,但这里记录了各种各样的东西;)

编辑/更新2

令我困惑的案例就在这里.

最终编辑

好的,这是一个相当混乱的帖子.所以澄清:我期待的是一种类似于此的行为:

function makeClosure()
{
    function fromThisFunc()
    {
        console.log(this);
    }
    return fromThisFunc;
}

var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
Run Code Online (Sandbox Code Playgroud)

引起我的是,该函数anyFunc未在正确的范围内声明,因此this指向窗口对象.我通过阅读我在网上找到的一个古老的卷轴找到了这个.

但是发生了一些更复杂的事情,因为globalVar现在引用的函数对象是使用[[scope]]属性创建的,该属性引用包含属于创建它的执行上下文的Activation/Variable对象的作用域链(和全球对象).现在,无法对Activation/Variable对象进行垃圾收集,因为globalVar引用的函数对象的执行需要将整个作用域链从其[[scope]]属性添加到为每次调用创建的执行上下文的作用域中.它.

所以我需要做的是简化而不是复杂化:

function fromThisFunc()
{
    console.log(this);
}

function makeClosure(funcRef)
{
    //some code here
    return funcRef;
}
Run Code Online (Sandbox Code Playgroud)

那应该有用,对吗?

PS:除了Alnitak的回答,我会这么做,但特别感谢Felix Kling的所有耐心和信息.

Aln*_*tak 4

只要您致电:

return func(par);
Run Code Online (Sandbox Code Playgroud)

您正在创建一个新的作用域(带有它自己的this),在这种情况下,因为您没有指定对象,this === window通常或在严格模式下未定义。被调用函数不会继承this调用范围内的任何内容。

为此设置值的方法是:

myobj.func(par);  // this === myobj
Run Code Online (Sandbox Code Playgroud)

或者

func.call(myobj, ...)  // this === myobj
Run Code Online (Sandbox Code Playgroud)

还有:

  • @EliasVanOotegem:我认为你的测试在某种程度上是有缺陷的,尤其是最后一个。每当你进行简单的函数调用“foo()”时,“this”将引用全局对象,无论该函数是在哪里定义的。您在什么环境下测试代码?在这种情况下,创建局部变量没有什么区别。该参数也是本地的。您的第一个修复在这里工作正常:http://jsfiddle.net/GErkX/ (2认同)