likes
comments
collection
share

this指向谁,当然是真正的调用者——拒绝“八股文”

作者站长头像
站长
· 阅读数 26

一句话概括this的指向

this指向是一个很重要,但也容易把大家搞蒙的知识点,再配合有些冗长的解释,让我们本不富裕的脑细胞更加雪上加霜,其实this的指向用一句话就可以概括

this指向真正的调用者

this绑定规则

将this的绑定规则分类来看,有助于我们进行理解

绑定规则this指向
默认绑定当函数直接在全局作用域下调用时,this 指向全局对象 window
隐式绑定当函数作为某个对象的方法被调用时,this 指向该对象
显式绑定使用 call、apply 或 bind 函数显式给 this 绑定对象
new 绑定使用 new 关键字创建实例时,this 指向新创建的对象
箭头函数绑定箭头函数没有自己的 this 绑定,它们会继承父级作用域中的 this 值

默认绑定

作为最简单的绑定方式,函数直接在全局作用域下调用时,this直接指向全局对象window

function foo(){
    console.log(this);
}
foo();  // window

隐式绑定

隐式绑定是指对象中的方法被调用时,this指向该对象

const obj = {
    name: "张三",
    sayName: function(){
        console.log(this.name);
    }
}
obj.sayName(); // 张三

上述例子中,this指向的是obj对象

注意: 如果函数被多层对象包裹,那么this仅与最后一层对象有关系,我们来看下面的例子

const obj1 = {
    name: "小明",
    obj2: {
        name: "小红",
        sayName: function(){
            console.log(this.name);
        }
    }
}
obj1.obj2.sayName(); // 小红

在上面的例子中,尽管obj2obj1的属性,但实际上this指向的是obj2对象,而不是obj1

显式绑定

使用callapplybind函数显式绑定对象

call方法

call方法可以调用一个函数,并且指定函数内部this对象的值,它的第一个参数就是this要指向的对象

const person = {
  name: 'Alice'
};

function sayHello() {
  console.log('Hello, I am ' + this.name);
}

// 调用 sayHello 函数,并将 person 对象作为 this 对象
sayHello.call(person); // Hello, I am Alice

apply方法

apply方法与call方法类似,第一个参数也是this要指向的对象,它与call方法的区别在于后续参数,这里我们先不做过多讨论啦,先来看看例子吧

const person = {
  name: 'Alice'
};

function sayHello() {
  console.log('Hello, I am ' + this.name);
}

// 调用 sayHello 函数,并将 person 对象作为 this 对象
sayHello.apply(person); // Hello, I am Alice

bind方法

const person = {
  name: 'Alice'
};

function sayHello() {
  console.log('Hello, I am ' + this.name);
}

// 绑定 person 对象作为 sayHello 函数的 this 对象,并返回一个新函数
const sayHelloToPerson = sayHello.bind(person);

// 调用新函数
sayHelloToPerson(); // Hello, I am Alice

new 绑定

使用new关键字创建实例时,this指向新创建的对象

function Person(name){
    this.name = name;
}
const p = new Person("张三");
console.log(p.name); // 张三

注意: 在构造函数中使用return语句时,如果返回值不是一个对象而是一个基本数据类型,则会忽略返回值,直接返回this绑定的对象,让我们来看下面的例子

function Person(name){
    this.name = name;
    return "hello";
}
const p = new Person("张三");
console.log(p.name); // 张三

虽然构造函数返回的是字符串"hello",但p对象的name属性还是被设置成了"张三"

箭头函数绑定

箭头函数没有自己的this绑定,而是继承父级作用域中的this

const obj = {
    name: "张三",
    foo: function(){
        setTimeout(()=>{
            console.log(this.name);
        }, 1000)
    }
}
obj.foo(); // 张三

箭头函数中的this继承了foo属性的this指向,即obj对象

后语

在开发中,this指向非常重要,不同的绑定规则决定了this最终所指向对象的不同,按照默认绑定隐式绑定显式绑定new 绑定箭头函数绑定这5种方式来分类,有助于我们更好地理解 this背后鲜为人知的秘密

我是前端霸哥,愿你的代码中没有bug 写的不好的地方,欢迎各位小伙伴批评指正