this指向谁,当然是真正的调用者——拒绝“八股文”
一句话概括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(); // 小红
在上面的例子中,尽管obj2
是obj1
的属性,但实际上this
指向的是obj2
对象,而不是obj1
显式绑定
使用call
、apply
或bind
函数显式绑定对象
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 写的不好的地方,欢迎各位小伙伴批评指正
转载自:https://juejin.cn/post/7244783947821400125