理解 this 的指向是 JavaScript 中的一个核心难点,而普通函数和箭头函数的 this 行为差异是最容易混淆的地方。我们可以用「谁调用,指向谁」(普通函数)和「在哪定义,继承谁」(箭头函数)这两句话来概括,再结合具体例子就很好理解了。
在这里插入图片描述

一、普通函数:this 指向「调用它的对象」(动态绑定)

普通函数的 this 不是固定的,取决于「谁在调用它」,调用方式不同,this 指向就可能不同。就像现实中「工具的使用者决定了工具的作用对象」—— 同一把螺丝刀,A 用它拧螺丝,B 用它撬东西,作用对象(类似 this)是不同的。

例子1:函数作为「对象方法」被调用

当函数是对象的一个属性(方法)时,调用这个方法的对象就是 this 的指向。

let person = {
  name: "小明",
  sayHi: function() { 
    // 谁调用 sayHi?是 person 对象
    console.log(this.name); // this 指向 person,输出 "小明"
  }
};

person.sayHi(); // 调用者是 person → this 指向 person
例子2:函数在「全局作用域」被调用

如果函数没有明确的调用对象(直接在全局调用),this 会指向「全局对象」(浏览器中是 window,Node 环境中是 global)。

function sayHi() {
  // 没有明确调用者,默认是全局对象
  console.log(this); // 浏览器中输出 window 对象
}

sayHi(); // 等价于 window.sayHi() → this 指向 window
例子3:函数作为「构造函数」被调用(用 new

当用 new 关键字调用函数(此时函数是构造函数),this 会指向「新创建的实例对象」。

function Person(name) {
  this.name = name; // this 指向新创建的实例
}

let person1 = new Person("小红"); 
console.log(person1.name); // "小红" → this 指向 person1 实例
总结普通函数的 this 规律:
  • 谁调用函数,this 就指向谁;
  • 没有明确调用者 → 指向全局对象;
  • new 调用 → 指向新实例。

二、箭头函数:this 继承自「外层作用域」(静态绑定)

箭头函数没有自己的 this,它的 this 是「定义时就固定好的」,继承自外层作用域的 this(也就是箭头函数写在哪个作用域里,就用哪个作用域的 this)。
可以理解为:箭头函数像个「复读机」,它的 this 完全照搬外层环境的 this,不管谁调用它都不会变。

例子1:箭头函数作为「对象方法」(和普通函数对比)
let person = {
  name: "小明",
  // 普通函数方法
  sayHi1: function() {
    console.log(this.name); // 调用者是 person → 输出 "小明"
  },
  // 箭头函数方法
  sayHi2: () => {
    // 箭头函数定义在 person 对象的外层(全局作用域)
    // 所以 this 继承全局的 this(window),而 window 没有 name 属性
    console.log(this.name); // 输出 undefined
  }
};

person.sayHi1(); // 正常输出 "小明"
person.sayHi2(); // 输出 undefined(因为 this 指向 window)

关键:箭头函数 sayHi2 定义在全局作用域(person 对象只是它的载体,不是它的外层作用域),所以 this 继承全局的 window,而不是调用它的 person 对象。

例子2:箭头函数在「嵌套函数」中(解决普通函数的 this 丢失问题)

这是箭头函数最常用的场景:当需要在嵌套函数中保留外层 this 时。

let timer = {
  name: "计时器",
  start: function() {
    // 普通函数作为定时器回调:this 会指向 window(丢失外层 this)
    setTimeout(function() {
      console.log("普通函数:", this.name); // 输出 "普通函数: undefined"(this 是 window)
    }, 100);

    // 箭头函数作为定时器回调:this 继承外层的 this(即 timer 对象)
    setTimeout(() => {
      console.log("箭头函数:", this.name); // 输出 "箭头函数: 计时器"(this 是 timer)
    }, 100);
  }
};

timer.start();

原因

  • 普通函数的回调在定时器中被 window 调用,所以 this 指向 window
  • 箭头函数的回调定义在 start 方法内部(外层作用域的 thistimer),所以 this 继承 timer
总结箭头函数的 this 规律:
  • 箭头函数没有自己的 this,它的 this 由「定义时的外层作用域」决定;
  • 一旦定义,this 就固定不变,无论谁调用它都不会改变;
  • 外层作用域指的是箭头函数「写在哪里」,而不是「被谁调用」。

三、一句话对比记忆

函数类型 this 指向规则 核心特点
普通函数 谁调用,指向谁 动态变化(取决于调用方式)
箭头函数 在哪定义,继承哪 静态固定(定义时就确定)

实际开发中的建议

  • 当需要 this 指向调用对象时(比如对象的方法),用普通函数;
  • 当需要保留外层 this 时(比如嵌套函数、回调函数),用箭头函数;
  • 箭头函数不适合作为对象的方法(因为 this 不会指向对象本身)。

多写几个对比案例,观察 this 的输出结果,很快就能掌握这个区别了!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐