一文搞懂函数 this 指向
1.案例
箭头函数的应用,让里面的 this 继承外面的函数的,从而得到对象里面的内容!
1.例子一
Tabs.prototype.change = function () {
for (let i = 0; i < this.headerItems.length; i++) {
this.headerItems[i].addEventListener(
this.type,
() => {
//这里必须用箭头函数,让其继承change函数的this(为什么本身是指向tabs对象的?因为change方法被实例对象tabs调用了,隐式绑定this),否则this指向的就不是tabs对象了,因为普通函数是谁调用就指向谁
for (let m = 0; m < this.headerItems.length; m++) {
this.headerItems[m].classList.remove("active");
this.boxItems[m].classList.remove("active");
}
this.headerItems[i].classList.add("active");
this.boxItems[i].classList.add("active");
},
false
);
}
};
2.例子二
因为箭头函数(()=>{}
)没有自己的 this
上下文,它会捕获其所在的词法作用域(也就是定义它的函数或对象的作用域)的 this
值。在这个例子中,箭头函数 next
捕获了 Symbol.iterator
函数的 this
,而 Symbol.iterator
函数是在 obj
对象内部定义的,因此 this
指向了 obj
对象。
箭头函数的 this
是词法作用域绑定的,它会捕获定义时(也就是箭头函数被创建时)所处的上下文的 this
,而不会受到函数调用方式的影响。
var obj = {
code: 200,
name: "kerwin",
list: ["aaaa", "bbbb", "ccc"],
[Symbol.iterator]: function () {
let index = 0; //闭包存储
return {
next: () => {
//这里必须用箭头函数,让它的this继承Symbol.iterator函数的this,从而指向obj对象!
if (index < this.list.length) {
return {
value: this.list[index++],
done: false,
};
} else {
return {
value: undefined,
done: true,
};
}
},
};
},
};
2.详解
箭头函数与普通函数 this 的区别?箭头函数如何捕获 this?以及对于对象的 this 的理解?
在 JavaScript 中,普通函数的 this
取决于函数被调用时的上下文,可以通过不同的方式调用函数来改变 this
的指向,比如使用 call
、apply
或者作为对象的方法调用。而箭头函数没有自己的 this
上下文,它会捕获定义时(函数创建时)的上下文的 this
。
注意:箭头函数捕获的(继承的)一定是它外层距离最近的普通函数的 this,如果没有,那么最终会指向 window/undefined
注意:对象本身是没有 this 的,而是一种用于引用对象的符号,它主要是在一个对象调用一个方法(普通函数)的时候,会把 this 传递给函数(隐式 this 绑定),但是对象本身并不能作为箭头函数的外层 this 供其继承!
在 JavaScript 中,对象是具有属性和方法的实体,而 this
是用来引用当前对象的关键字。在对象内部的方法中,可以使用 this
关键字引用对象本身。
//1.fullName是箭头函数的时候,向外继承,外层没有普通函数,this指向window
const person = {
firstName: "John",
lastName: "Doe",
fullName: () => {
return this.firstName + " " + this.lastName;
},
};
console.log(person.fullName()); //undefined undefined
//2.fullName是箭头函数的时候,向外继承,继承fun函数的this,fun为箭头函数,继续向外继承,外层没有普通函数,所以this指向window,最终fullName的this也指向了window
const person2 = {
firstName: "hao",
lastName: "wenhai",
fun: () => {
return {
firstName: "John",
lastName: "Doe",
fullName: () => {
return this.firstName + " " + this.lastName;
},
};
},
};
console.log(person2.fun().fullName()); //undefined undefined
//3.fullName是箭头函数的时候,向外继承,继承fun函数的this,fun为普通函数,被person3调用,所以this指向person3对象,最终fullName的this也指向person3对象
const person3 = {
firstName: "hao",
lastName: "wenhai",
fun: function () {
return {
firstName: "John",
lastName: "Doe",
fullName: () => {
return this.firstName + " " + this.lastName;
},
};
},
};
console.log(person3.fun().fullName()); //hao wenhai
//4.fullName是普通函数的时候,不用向外继承,fun的返回对象调用fullName,所以this指向返回对象!
const person4 = {
firstName: "hao",
lastName: "wenhai",
fun: function () {
return {
firstName: "John",
lastName: "Doe",
fullName: function () {
return this.firstName + " " + this.lastName;
},
};
},
};
console.log(person4.fun().fullName()); //John Doe
3.理解
搞懂函数的 this 指向是非常必要的
这对于避免上下文调用的 bug,理解类里面的函数的 this 指向和作用也是很有帮助的!
类里面的 this?
在 JavaScript 中,类中的 this
关键字指向当前实例化的对象,也就是类的实例。类中的 this
可以用来访问和操作实例的属性和方法。
例如,下面是一个简单的类示例:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
//一定用普通函数,否则不能指向我们当前的实例对象!
return this.firstName + " " + this.lastName;
}
}
const johnDoe = new Person("John", "Doe");
console.log(johnDoe.getFullName()); // 输出:John Doe
在这个例子中,this.firstName
和 this.lastName
用来访问类的实例(即 Person
的实例)的属性。当你创建一个类的实例(const johnDoe = new Person('John', 'Doe')
),this
就指向该实例,可以通过 this
访问实例的属性和方法。
需要注意的是,当在类的方法中使用 this
时,确保方法是普通函数而不是箭头函数,以便正确绑定 this
。箭头函数没有自己的 this
上下文,会捕获其外层最近一层非箭头函数的 this
。在类中,通常我们会使用普通函数来确保正确的 this
绑定到实例。