我很难理解下面的代码。
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var a = 4;
obj.foo();
setTimeout( obj.foo, 100 );
setTimeout( obj.foo.bind(obj), 100 );
它的输出为2,4,4,我无法理解。
答案 0 :(得分:2)
第一种情况,
obj.foo();
this
内的foo
将指向obj
,因为您已将该函数指定为该特定对象的属性。
第二种情况,
setTimeout( obj.foo, 100 );
在setTimeout中,传递的函数将在窗口的上下文中eval
。所以这里var a = 4;
在窗口的上下文中执行,并成为窗口的属性。在函数this
中访问foo
时,在此特定情况下会指向window
。
第三种情况,
setTimeout( obj.foo.bind(obj), 100 );
您刚刚将obj
this
绑定到函数foo
。即使在窗口的上下文中评估函数,也不会更改绑定的this
值。这是bind
函数背后的规则。因此,此处this
不会从obj
更改为window
。
答案 1 :(得分:2)
this
关键字在差异上下文中的行为略有不同。
在全局执行上下文中(在任何函数之外),这指的是全局对象,无论是否处于严格模式。
在函数内部,其值取决于函数的调用方式。
function foo() {
console.log(this)
}
在非严格模式下,this
将默认为全局对象
在严格模式下,this
将默认为未定义
call
或apply
function foo() {
console.log(this)
}
var o = {'name': 'test object'};
foo.call(o) // log object `o`
可以使用call或apply方法将 this
绑定到调用中的特定对象。
bind
bind
方法返回一个函数,该函数使用bind
中的特定对象作为函数中的this
对象。
function foo() {
console.log(this)
}
var o = {'name': 'test object'};
bar = foo.bind(o)
bar() // log object `o`
有关详细信息,请参阅此链接:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this
在这种情况下,obj.foo();
this
函数foo
为obj
,因此this.a
引用obj.a
在这种情况下,setTimeout( obj.foo, 100 );
obj.too
是对函数foo
的引用。 setTimeout
将在全局范围内执行它。
在这种情况下setTimeout( obj.foo.bind(obj), 100 );
,obj.foo.bind(obj)
会返回对this
与obj
绑定的函数的引用。 setTimeout
将在obj
答案 2 :(得分:1)
您需要了解this
的行为方式。它被称为函数执行上下文,您可以阅读有关here的更多信息。
在第一种情况下,函数在对象obj
的上下文中调用,因为使用了属性访问器.
(obj.foo
),因此this
指向obj
。
在第二种情况下,将独立函数传递给setTimeout
,它将在全局上下文中调用,this
指向窗口。
obj.foo()
与var f = obj.foo; f()
在第三种情况下,您将函数调用的上下文绑定到obj
,this
再次指向obj。详细了解bind
here。
答案 3 :(得分:0)
尝试将alert(this);
置于foo()方法中以了解上下文。
obj.foo();
=>在对象上下文中运行,因此结果将是a
=>内obj
的值。 2
setTimeout( obj.foo, 100 );
=>在窗口上下文中运行,var a = 4
在窗口上下文中,this.a
给出4 {this
这里是window
)
并且最后一行将再次具有对象context => 2