likes
comments
collection
share

前端面试系列-JS篇-this指向

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

相信大家在刚开始的时候都会对于这奇怪的 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 方法的调用对象就是 windowthis 也就指向 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 对象)。

技巧:它的外层没有函数,thiswindow;外层有函数,看外层函数的 this 是谁,它的 this 就是谁。

function outerFunction() {
  const arrowFunction = () => {
    console.log(this); // 指向外部函数作用域中的 this
  };

  arrowFunction();
}

outerFunction();

在这个例子中,箭头函数 arrowFunction 是在 outerFunction 函数内部定义的,因此它的 this 指向的是 outerFunctionthis,那 outerFunctionthis 指向谁呢?

outerFunction 的调用者,大家明白了吗?是 window ,不明白的要好好去看第一条哦

apply,call,bind 调用模式

apply,call,bind 调用模式下,this 指向第一个参数。

这里先简单介绍一下 apply,call,bind ,详情可查看(再挖一个坑)

前端面试系列-JS篇-this指向

通过使用callapply方法,可以指定函数执行时的 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 指向当前对象;在使用callapply方法调用时,可以手动指定 this 的指向。在箭头函数中,this 的指向在定义时就确定了,最接近的包含它的非箭头函数的 this指向,如果没有,则指向全局对象。

看完这篇文章,相信大家都对 this 指向有了一个全新的认识,使用的话也不会对 this 指向感到困惑了,这样也能愉快的 coding 了

最后祝大家变得更强!

转载自:https://juejin.cn/post/7237020208647847997
评论
请登录