前端面试系列-JS篇-this指向
相信大家在刚开始的时候都会对于这奇怪的 this
指向感到很困惑,this
指向为什么是动态?它又有什么规律呢?通过这篇文章,这些问题都可以得到解答。
什么是 this
在 JavaScript
中,this
是一个关键字,它指向当前执行上下文中的对象。执行上下文可以是函数执行上下文,也可以是全局执行上下文。this
关键字是在函数调用时确定的,因此它的指向是动态的而不是静态的。
为什么会有 this
指向问题
this
关键字的使用是基于函数式编程的概念。在函数式编程中,this
关键字被赋予了特殊的含义,它不再是指向调用者的简单指针,而是表示函数当前运行的环境,也就是 this
关键字的值是在函数运行时动态确定的。
那为什么 JavaScript
中函数的调用方式和上下文是动态的呢?
这是因为在 JavaScript
中,函数作为一等公民,可以作为变量、对象的属性、数组元素、参数等进行传递。这种灵活性使得 JavaScript
可以在不同的上下文中使用相同的代码,并且可以在运行时动态地改变函数的调用方式和上下文。
例如,可以使用 call、apply 或 bind
方法来手动指定函数执行时的 this
值,从而改变函数的上下文。可以将函数作为对象的方法调用,从而改变函数的调用方式。可以将函数作为参数传递给其他函数,从而在其他函数中调用该函数并改变函数的上下文。
这种动态性使得 JavaScript
可以灵活地处理不同的情况,并且可以在运行时动态地改变代码行为。但是,这也会带来一些问题,因为函数的调用方式和上下文是动态的,因此可能会出现意外的 this
指向问题。为了避免这种问题,我们需要小心地处理函数的调用方式和上下文,并根据需要手动指定函数执行时的 this
值。
this
的指向
- 函数调用模式下,
this
永远指向离它最近的调用对象,如果没有调用对象,this
指向window
- 构造函数模式下,构造函数中的
this
指向实例化对象- 箭头函数中的
this
指向的是外部作用域的this
apply,call,bind
调用模式下,this
指向第一个参数;
函数调用模式
this
永远指向离它最近的调用对象,如果没有调用对象,this
指向 window
我们先从简单的开始
function print() {
console.log(this)
}
print();
这里的 this
指向的是 window
,为什么呢?
我们可以理解成 print
本身就是全局方法,挂载在 window
下,所以 print()
也就等于 window.print()
,那么 print
方法的调用对象就是 window
,this
也就指向 window
我们继续,加一点难度
function print() {
console.log(this)
}
let obj = {
print,
}
obj.print();
这里的this指向的是obj,因为print方法的调用对象就是obj,所以this指向的是obj
继续加大难度
function foo () {
function inner () {
console.log(this)
}
inner()
}
foo()
大家知道这里的 this
指向谁吗?是 window
还是 foo
?
3,2,1 揭晓答案
这里的 this
指向的是 window
,不要被他繁杂的代码所迷惑,就记住在函数调用模式下,this指向离它最近的调用对象,所以 inner
执行的时候没有调用对象,那么指向的就是 window
好了,调用模式下讲完了,我们接下来继续构造函数模式的 this
指向问题
构造函数模式
构造函数中的 this
指向实例化对象
function Person(name) {
this.name = name;
}
const person = new Person("Alice");
console.log(person.name);
这里的 this
指向新创建的 Person
对象,person.name
打印出来自然是 Alice
。
在构造函数被调用时,JavaScript
引擎会创建一个新的对象并将其赋值给 this
,然后执行构造函数中的代码,并最终返回 this
。详情可以查看 New
的原理(这里先挖个坑)。
箭头函数中的 this
箭头函数中的 this
指向的是外部作用域的 this
与普通函数不同,箭头函数的 this
指向在函数定义时就确定了,而不是在函数调用时确定。箭头函数的 this
指向最接近的包含它的非箭头函数的 this
指向。如果箭头函数没有包含在任何非箭头函数中,则 this
指向全局对象(在浏览器环境中是 window
对象)。
技巧:它的外层没有函数,this
是 window
;外层有函数,看外层函数的 this
是谁,它的 this
就是谁。
function outerFunction() {
const arrowFunction = () => {
console.log(this); // 指向外部函数作用域中的 this
};
arrowFunction();
}
outerFunction();
在这个例子中,箭头函数 arrowFunction
是在 outerFunction
函数内部定义的,因此它的 this
指向的是 outerFunction
的 this
,那 outerFunction
的 this
指向谁呢?
看 outerFunction
的调用者,大家明白了吗?是 window
,不明白的要好好去看第一条哦
apply,call,bind 调用模式
apply,call,bind 调用模式下,this 指向第一个参数。
这里先简单介绍一下 apply,call,bind
,详情可查看(再挖一个坑)
通过使用call
或apply
方法,可以指定函数执行时的 this
指向。例如:
function sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
const person1 = { name: "Alice" };
const person2 = { name: "Bob" };
sayHello.call(person1); // this指向person1对象
sayHello.apply(person2); //this指向person2对象
总结
在 JavaScript
中,this
关键字指向当前执行上下文中的对象。在全局作用域中,this
指向全局对象(在浏览器环境中是 window
对象)。在函数中,this
的指向可能会根据调用方式而变化。在对象方法调用和构造函数调用中,this
指向当前对象;在使用call
或apply
方法调用时,可以手动指定 this
的指向。在箭头函数中,this
的指向在定义时就确定了,最接近的包含它的非箭头函数的 this
指向,如果没有,则指向全局对象。
看完这篇文章,相信大家都对 this
指向有了一个全新的认识,使用的话也不会对 this
指向感到困惑了,这样也能愉快的 coding 了
最后祝大家变得更强!
转载自:https://juejin.cn/post/7237020208647847997