JavaScript中this的指向取决于function被谁调用,而不取决于其定义。
示例一
function fn() {
console.log(this)
}
fn()
上例中,fn是被全局对象调用,所以this指向全局对象。
示例二
const obj = {
foo: function () {
console.log(this)
}
}
let fn = obj.foo
fn()
obj.foo()
上例中,fn方法指向obj.foo,由于fn方法被全局对象调用,因此this指向全局对象。而直接调用obj.foo()
,此时foo方法被obj调用,因此this指向obj。
示例三
function Foo() {
console.log(this)
}
const f = new Foo()
上例中,Function Foo被当作构造函数进行了实力化,此时this指向实力化对象f。
ES2015中的class关键字是一种语法糖,其本质还是声明一个构造函数,因此其内部this指向可参考构造函数。
示例四
function foo() {
return () => {
console.log(this)
}
}
foo()()
箭头函数虽然也是一种函数,但是其不改变内部this指向,也就是说在查找箭头函数内部this指向时,查找的依然是包裹它的function的调用者。在上例中,foo函数返回的函数是被全局对象调用,因此this指向全局对象。
基于上面的四个例子,可以总结出在JavaScript中查找this的步骤为:
- 沿着作用域链由内向外查找查找最近的function(箭头函数不是function),看这个function最终被谁调用。
- 被全局对象调用(作为函数调用),如
foo()
, this指向全局对象。 - 被其他对象调用(作为方法调用),如
foo.bar()
,this指向最终调用这个方法的对象。 - 被当作构造函数调用,如
new Person
,this指向新生成的实力化对象。 - 特殊调用,如
fn.call, fn.apply, fn.bind
,此时this指向调用时传入的参数。
- 如果找不到function,this就指向全局对象。
this指向的全局对象是什么?
在上面提到很多次this指向全局对象,那这个全局对象到底是什么?
浏览器环境下
- 非严格模式下,全局对象为window。
- 严格模式下,全局对象为undefined。
node环境下
如果在命令行中通过node *.js 执行时,分为下面两种情况。
- 如果this没有在任何函数作用域中
if (true) {
console.log(this)
}
console.log(this)
// true
console.log(this === module.exports)
在上例中,this指向{}。
因为nodejs为保证文件的模块作用域,在执行文件代码时,会为所有的文件代码添加一个包裹函数,上面的执行类似于:
// exports 指向module.exports
function wrapped(exports) {
if (true) {
console.log(this)
}
console.log(this)
}
wrapped()
因此this会指向{}。
- 如果this处在函数作用域中,this指向调用者。
function fn() {
console.log(this)
}
fn()
在上例中,fn是全局对象调用,而node环境中,全局对象是Global,因此this指向Global。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。