与面向对象中的 this 不同,要判断javascript函数中的 this 到底指向何方,需要知晓一些规则,然后根据具体的执行场景去判断。
this 到底指向那里?
先来看一个经典的例子:
1 2 3 4 5 6 7 8 9 10 11 12
| function getName() { console.log(this.name) }
var stu = { name: "tom", getName: getName }
console.log(stu.getName())
setTimeout(stu.getName, 100)
|
把以上的代码放入一段 HTML 中,例如:
1 2 3 4 5 6 7 8 9
| <!DOCTYPE html> <html> <body> Please see the console. </body> <script type="text/javascript"> </script> </html>
|
就可以看到结果。
确定 this 的规则
首先,找到函数的直接调用位置,然后根据以下规则来顺序判断:
- 在由 new 创建的新对象中,绑定到新创建的对象。
- 由call或者apply(或者bind)调用,绑定到指定的对象。
- 由上下文对象调用,绑定到那个上下文对象。
- 默认:在严格模式下绑定到undefined,否则绑定到全局对象。
下面我们来解释一下每条规则
在由 new 创建的新对象中
看下面的代码:
1 2 3 4 5 6 7 8 9 10
| function foo(v) { this.a = v console.log(this.a) }
var bar = new foo(2)
var a = 100
console.log(bar.a)
|
显式绑定中
通过执行call或者apply(或者bind)调用,绑定到指定的对象。
观察以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function foo() { console.log(this.a) }
var obj = { a: 42, }
var a = 2
var other = function() { foo.call(obj) }
|
由上下文对象调用决定(隐式绑定)
观察以下代码:
1 2 3 4 5 6 7 8 9 10 11
| function foo() { console.log('foo') console.log(this.a) }
var obj = { a: 42, foo:foo }
obj.foo()
|
默认行为
观察下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function baz() { console.log('baz') bar() }
function bar() { console.log('bar') foo() }
function foo() { console.log('foo') console.log(this.a) }
var a = 2
baz() foo()
|