追本溯源:this
首先看mdn中的解释:在绝大多数情况下,函数的调用方式决定了this的值,this不能在执行期间被赋值,并且在每次函数被调用时this的值也可能会不同。
重点:函数的调用方式决定了this的值
,也就是说this在绝大多数的情况下指向调用它的那个对象
其实在我们实际编码中,经常会使用this.xxx
,有时候就会出现this.xxx is undefined
的错误。就是有时候代码执行上下文中的this并不是我们想当然的那个对象。
ES5引入了bind方法来设置函数中的this的值,而不用考虑函数是如何被调用的。ES6引入了箭头函数,箭头函数不提供自身的this绑定
无论在何处我们都可以直接使用globalThis来获取全局对象
function someFunction() {
return this;
}
// `true`:
console.log(someFunction() === globalThis);
其实this是和执行上下文绑定的,所以this也可以分为三种:
- 全局上下文中的this
- 函数上下文中的this
- eval中的this(基本不使用)
根据mdn
的定义我们知道了,绝大多数都是指向调用他的那个对象除了绝大多数的情况,还有一些特殊的情况需要单独注意一下:
- 箭头函数(arrow function):与外部的this相同
const outerThis = this
const arrowFunction = () => {
console.log(this === outerThis)
}
arrowFunction() // true
一些其他的情况:
-
bind:不会改变this指向
-
call/apply:不会改变this指向
-
作为其他Object的属性被调用:不会改变this指向
const obj = {arrowFunction}; // `true` obj.arrowFunction();
-
使用new调用函数:
new arrowFunction() // TypeError: arrowFunction is not a constructor
- class中使用箭头函数:this总是指向class的实例
class Whatever { someMethod = () => { // 总是指向Whatever的实例 console.log(this); }; }
总的来说,如果使用了箭头函数,函数内的this就基本上指向外部的this
-
new:等价于
Object.create(Whatever.prototype)
-
bind:this指向不会被改变
const BoundMyClass = MyClass.bind({foo: 'bar'}); new BoundMyClass();
-
作为其他Object的属性被new:this指向不会被改变
const obj = {MyClass}; // Logs `true` - parent object is ignored: new obj.MyClass();
-
-
使用call apply bind
- call apply可以指定一个this值和单独给出一个或者多个参数来调用一个函数
- bind会创建一个新函数,这个新函数的this是指定的
参考文章: what is this