this指向
总结this的指向
- 直接调用函数,this 指向全局对象(严格模式是 undefined)
- 在函数外,this 指向全局对象(严格模式是 undefined)
- 通过对象调用或 new 一个函数,this 指向调用的对象或新对象
- 使用call/apply/bind 方法调用,this 指向被绑定的对象
- 箭头函数中的 this 有外层(函数或全局)作用域来决定的
一个个举例
1. 直接调用函数,this 指向全局对象(严格模式是 undefined)
function sayName() {
console.log(this); // global
console.log(this.name); // undefined
}
sayName(); // this => global
'use strict';
function sayName() {
console.log(this); // undefined
console.log(this.name); // TypeError: Cannot read property 'name' of undefined
}
sayName(); // this => undefined
2. 在函数外,this 指向全局对象(严格模式是 undefined)
console.log(this === module.exports); // true
Tips:
当在Node REPL 交互环境中输入 this === global 才为 true,因为在 一个 js 文件中执行时,Node 文件顶层 this 是模块导出对象,只有全局作用域 / 独立函数调用,this 才是 global
'use strict';
console.log(this === module.exports); // true
总结:
| 执行环境 | this 指向 | this === global |
|---|---|---|
Node .js 文件顶层 | module.exports | ❌ false |
| Node REPL 命令行 | global(全局对象) | ✅ true |
| 普通函数独立调用(非严格) | global | ✅ true |
| 普通函数独立调用(严格) | undefined | ❌ false |
| 定时器 / IO 回调(非严格) | global | ✅ true |
| 箭头函数 | 继承外层 this | 视情况而定 |
3. 通过对象调用或 new 一个函数,this 指向调用的对象或新对象
function Person() {
this.name = 'summer';
}
let person = new Person();
console.log(person.name); // summer
4. 使用call/apply/bind 方法调用,this 指向被绑定的对象
function sayName() {
console.log(this.name);
}
let person = {
name: 'summer',
};
sayName.call(person); // summer
5. 箭头函数中的 this 有外层(函数或全局)作用域来决定的
let sayName = () => {
console.log(this);
};
sayName(); // module.exports
箭头函数不新开 this,直接借外面的
const obj = {
name: '张三',
say: function() {
setTimeout(() => {
// 箭头函数:继承外层 say 函数的 this(就是 obj)
console.log(this.name); // 张三
}, 1000);
}
};
obj.say();
普通函数有自己的 this,作为普通函数调用时,会在其执行上下文中将其 this 指向 window,因为它是独立调用的。
const obj = {
name: '张三',
say: function () {
setTimeout(function () {
// 普通函数:定时器回调独立调用,this → 全局(window/global)
console.log(this.name); // undefined
}, 1000);
},
};
obj.say();
核心原理:
普通函数:this 只由「调用方式」决定,和 定义位置、作用域、闭包、[[Scope]] 全都无关。
箭头函数:this 只由定义时的外层作用域决定,跟怎么调用完全无关