js中的this指向问题

88 阅读2分钟

经常会在一些群里或者面试中都会问到关于this指向问题,总结一下关于this指向的几种情形。

将this的指向大致分为以下几类:(以下只讨论在非严格模式下中this指向)

隐式绑定:

1.直接调用

直接调用也就是在函数内部使用this,此时this指向把函数当成方法调用的上下文对象(在网页的全局上下文中调用函数时,this指向window)。

1.函数独立调用,this默认绑定window(注意:非严格模式)

2.obj对象调用

函数方法作为对象属性调用,this指向调用方法的对象 区分以下两个代码中this指向

let obj ={
  name:'name',
  foo: function(){
    console.log(this)
  }
}
let fn = obj.foo
obj.foo()
fn()

很明显obj.foo()中this指向的是obj,fn()中this指向的是window。

obj.foo()此时方法调用的上下文对象就是obj,fn()此时方法调用的上下文对象是wiindow/

显示绑定:

call()、apply()、bind() 都是用来重定义this的。

三者的区别:

call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数就有差别了

call和bind的第二个参数是一样的,都是直接传入参数用逗号隔开,而apply需要把传入参数放在一个数组中作为参数传入。

bind相比call和apply区别在于:bind会返回新的函数必须要调用它才会执行。

function Person(name){
  this.name = name;
}
Person.prototype = {
  constructor: Person,
  showName: function(){
    console.log(this.name);
  }
}
var person = new Person('xxx');
  person.showName();
  
var animal = {
  name: 'yyy'
}

person.showName.call(animal);

person.showName.apply(animal);

person.showName.bind(animal)();//不会立即执行,需要调用

特殊绑定:

构造函数 (new绑定)

构造函数的this会指向构造函数创建的新对象,在我们执行new创建构造函数时我们在new中就对this进行了操作:

  1. 创建一个空对象,将它的引用赋给 this,继承函数的原型;
  2. 通过 this 将属性和方法添加至这个对象;
  3. 最后返回 this 指向的新对象,也就是实例(如果没有手动返回其他的对象)

箭头函数

this是根据外层作用域来决定this指向,也就是定义箭头函数的上下文。

外层作用域判断就与其他this绑定规则相同。我们判断一下下面代码中this指向哪里?

const obj = {
    i: 10,
    b: () => console.log(this)
};
obj.b(); 

此处b函数是一个箭头函数,因为它是在window上下文中定义的此时this指向window。

因为箭头函数中this绑定的优先级是最高的所以我们不需要再根据obj.b()调用判断。

优先级

箭头函数>构造函数>bind>apply>call>obj.>直接调用

如果有更好的区分方式或者错误欢迎指出。