与JavaScript匿名函数中的“this”对象混淆

时间:2009-12-30 17:55:39

标签: javascript scope this

您好我有以下我试图运行的JavaScript代码。我的目标是在JavaScript中掌握this在不同范围和不同类型的调用中的含义。

如果您查看下面的代码:我有一个内部匿名函数,它被分配给innerStuff变量。在那个匿名函数中this指向window对象而不是外部函数对象或其他任何东西。事件虽然它仍然可以访问函数的变量。

无论如何,我不确定,为什么会这样;但是如果你查看下面的代码,我会以this的形式将that传递给innerStuff,它可以正常工作并在控制台中打印带有doofus属性的对象。

    var someStuff = {
        doofus:"whatever",
        newF: function()
        {
            var that = this;
            console.log(that);
            var innerStuff = function(topThis){
                console.log(topThis);
            };

            return innerStuff(that);
        }
    }

    someStuff.newF();

现在我只是改变了一点代码。而不是将其分配给innerStuff,我只是通过调用它直接返回该函数,如下所示:

    var someStuff = {
        doofus:"whatever",
        newF: function()
        {
            var that = this;
            console.log(that);
            return function(that){
                console.log(that);
            }();
        }
    }

    someStuff.newF();

这为内部匿名函数打印undefined。是因为作为参数传递的that与外部函数中定义的that之间存在冲突吗? 我认为参数会覆盖可见性。为什么价值不会保留?

这完全令人困惑。

另一方面,如果我没有通过that,而只是使用它,因为可见性存在,结果是正确的并且符合预期。

我错过了什么?它是变量之间的冲突,存在于相同的范围内吗? 是否有充分的理由,内部函数this绑定到window对象?

3 个答案:

答案 0 :(得分:9)

JavaScript中的

this指的是您调用方法的对象。如果您将函数调用为someObject.functionName(args),则this将绑定到该对象。如果您只是调用一个裸函数,就像functionName(args)一样,那么this将绑定到window对象。

在第二个示例中的newF内部,您正在隐藏内部函数中的that变量,但没有将任何内容传递给它,因此未定义。

        var that = this;
        console.log(that);
        return function(that){
            console.log(that);
        }();

如果你想要一些与你的第一个例子相同的东西(将that传递给内部函数),你可能需要以下内容:

        var that = this;
        console.log(that);
        return function(that){
            console.log(that);
        }(that);

或者下面,如果你不想遮蔽它并只使用外部函数的绑定:

        var that = this;
        console.log(that);
        return function(){
            console.log(that);
        }();

答案 1 :(得分:1)

在第二个示例中,当您调用匿名函数时,未定义参数that(您没有向其传递任何内容。)您可以这样做:

    newF: function()
    {
        var that = this;
        console.log(that);
        return function(that){
            console.log(that);
        }(that); // note that we are passing our 'that' in as 'that'
    }

这将保持变量的正确值。

但是,既然您正在考虑上面的var that,那么您也可以删除函数参数:

    newF: function()
    {
        var that = this;
        console.log(that);
        return function(){
            console.log(that);
        }(); // 'that' is referenced above.
    }

至于为什么匿名函数windowthis:无论何时调用没有上下文的函数(即somef() vs context.somef()this将指向window对象。

您可以覆盖该内容并使用.apply(context, argumentsArray) or .call(context, arg1, arg2, arg3)在函数上传递this。一个例子:

    newF: function()
    {
        console.log('Outer:', this);
        var innerF = function(){
            console.log('Inner:', this);
        };
        return innerF.apply(this,arguments);
    }

答案 2 :(得分:1)

在您的第一个代码示例中,匿名函数虽然在作为someStuff对象成员的函数中声明,但它不是someStuff对象的成员。因此,该函数中的this是对窗口对象的引用。如果您想调用匿名函数并控制this引用,则可以执行以下操作:

var someStuff = {
    doofus:"whatever",
    newF: function()
    {
        var that = this;
        console.log(that);
        var innerStuff = function(){
            console.log(this);
        };

        return innerStuff.apply(this);
    }
}

someStuff.newF();

在第二个示例中,您实际创建了一个匿名函数,执行它,然后返回匿名函数返回的值。但是,您的匿名函数没有返回任何内容。此外,您有一个变量名称冲突。你可以这样做:

var someStuff = {
    doofus:"whatever",
    newF: function()
    {
        var that = this;
        console.log(that);
        return function(){
            console.log(that);
            return true;
        }();
    }
}

someStuff.newF();

我添加了返回true,因为你的函数应该返回一些东西,因为正在执行它的函数返回匿名函数的返回值。它是返回true还是false或字符串或对象或其他任何内容取决于方案。