为什么在将函数参数作为字符串或引用传递时,`this`会发生变化?

时间:2011-05-04 12:47:16

标签: javascript

看看这个:

var a = {
    b: function() {
      console.log(this); 
    }  
}

// Example 1
a.b(); // a

// Example 2    
eval('a.b()'); // a

// Example 3
setTimeout('a.b()', 100); // a

// Example 4
setTimeout(a.b, 100); // Window

// Example 5
var c = a.b;
c(); // Window

jsFiddle

假设预期结果 I 所期望的......

示例1

调用b()时,Object的属性this成为属性的Object,此处为父a。它产生了预期的结果。

示例2

eval()旨在采用其调用位置的执行上下文,在本例中为window。它也会产生预期的结果。

示例3

将字符串传递给setTimeout()时,我想它会遇到与eval()非常相似的事情。它也会产生预期的结果。

示例4

在此示例中,

this变为Window。这就是我感兴趣的。

实施例5

此处this变为Window,因为c的父对象为Window

  1. 当仅传递对某个功能的引用时(例如a.b),当使用this调用时,Window是否始终为()

  2. 唯一的方法是将this a作为字符串传递给setTimeout() / setInterval()

2 个答案:

答案 0 :(得分:7)

  

当只传递对函数的引用(例如a.b)时,用()调用它时它总是Window吗?

  

唯一的方法是将它作为一个字符串传递给setTimeout()/ setInterval()吗?

没有。改为创建一个新函数。

setTimeout(function() { a.b() }, 100);

答案 1 :(得分:1)

开发人员经常对javascript的关键字感到困惑。最重要的是要记住它是由电话提供的。

在第四个例子中:

// Example 4
setTimeout(a.b, 100); // Window

第一个参数是对函数的引用,因此在没有任何“父”对象的情况下调用它。由于调用不提供对象,设置为window

您对示例5的评论:

  

这里变成了Window,因为   c的父对象是Window。

并不是真的不对。因为函数调用不提供用作this的对象,所以它被设置为window(这是没有提供对象时的默认值)。

  

唯一的方法是保持这个作为一个   将它作为字符串传递给setTimeout()   / setInterval()?

没有。除了将其称为对象的属性之外,您可以使用callapply

var x = a.b;
x.call(a);