2009-12-30 119 views
2

嗨我有以下JavaScript代码,我试图运行。我的目标是在不同的范围和不同类型的JavaScript调用中掌握this的含义。与JavaScript中的“this”对象混淆匿名函数

如果你看下面的代码:我有一个内部匿名函数,它被分配到innerStuff变量。在这样的匿名函数中,this指向window对象,而不是外部函数对象或其他任何东西。尽管它仍然可以访问out函数的变量。

无论如何,我不确定,为什么会这样;但如果你看下面的代码,我通过this的形式thatinnerStuff以后,它工作得很好,并在控制台打印对象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(); 

此打印未定义内部匿名函数。是否因为参数that和外部函数中定义的that之间有冲突? 我以为参数会覆盖可见性。为什么价值不被保留?

这是非常令人困惑的。

另一方面,如果我没有通过that,而只是使用它,因为知名度是存在的,结果是正确的和预期的。

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

回答

9

this JavaScript中引用您称为方法的对象。如果您调用的函数为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); 
     }(); 
+0

啊!!我不能相信我错过了这一点。万分感谢。 – Priyank 2009-12-30 18:09:18

+0

那么,它*与完全不同于在其他语言中绑定方法是如何工作的... – bobince 2009-12-30 18:28:46

1

在你的第二个例子,当你调用匿名函数,参数没有定义(你没有向它传递任何东西。)你可以这样做:

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. 
    } 

至于为什么匿名函数有window为他们this:每当你调用一个函数不利用上下文(即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); 
    } 
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还是false,还是字符串或对象或其他任何依赖于场景的内容。

+0

我同意第一点,我可以使用“应用”调用,但第二点是不正确的。没有名称冲突,因为传递的参数会覆盖外部函数中的参数。 我做的错误是我在拨打电话时没有将param传递给匿名函数。 [正如Brian在上面的例子中所示]他的建议解决方案工作得很好,他的立场得到了纠正。 至于回报价值;我不认为我太在乎;我只是想看看这个/这个值在内部函数中的范围。 尽管感谢您的帮助。 – Priyank 2009-12-30 18:24:46