Skip to content

C12. this 上下文

2.1. 🌟 简单对象方法中的 this 指向对象本身

在面向对象编程中,this 是一个指向“当前对象”的特殊关键字。它如同导航仪,告诉代码“此刻正在操作哪一个对象”。

javascript
const person = {
  name: "Alice",
  sayHello: function() {
    console.log(`你好,我是${this.name}`); // this 指向 person 对象
  }
};

person.sayHello(); // 输出:你好,我是Alice

this 的绑定规则

  • 普通方法调用this 指向调用该方法的对象(如 person.sayHello() 中的 this 指向 person
  • 严格模式:如果函数无明确绑定对象,则 thisundefined
挑战题:为什么输出是 undefined?
javascript
function looseFunc() {
  console.log(this); // 非严格模式下指向全局对象(浏览器中是 window)
}
looseFunc(); // 输出:Window {...}

2.2. ⭐ JavaScript 类的语法中的 this

在 ES6 类语法中,this 用于访问实例属性和方法。

javascript
class Animal {
  constructor(name) {
    this.name = name; // this 指向新创建的实例
  }
  speak() {
    return `我是${this.name}`; // this 指向当前实例
  }
}

const dog = new Animal("旺财");
console.log(dog.speak()); // 输出:我是旺财

注意

  • 在构造函数 constructor 中必须通过 this 初始化属性
  • 类方法中的 this 自动绑定到当前实例

2.3. 🌟 不同函数的切换可能导致 this 上下文紊乱

当函数脱离对象调用时,this 的指向可能发生混乱。

javascript
const car = {
  brand: "Tesla",
  start: function() {
    setTimeout(function() {
      console.log(`启动 ${this.brand}`); // this 指向 window(非严格模式)
    }, 1000);
  }
};

car.start(); // 输出:启动 undefined

常见错误场景

  1. 回调函数(如 setTimeout、事件监听器)
  2. 提取方法为独立函数
  3. 通过 call/apply/bind 显式绑定
解决方案:保存 this 上下文
javascript
const car = {
  brand: "Tesla",
  start() {
    const self = this; // 保存 this 上下文
    setTimeout(function() {
      console.log(`启动 ${self.brand}`); // 正确输出:启动 Tesla
    }, 1000);
  }
};

2.4. 函数原型链上的 this 行为

在原型链方法中,this 指向调用该方法的对象实例。

javascript
function Shape() {}
Shape.prototype.getInfo = function() {
  return `类型:${this.type}`; // this 指向具体实例
};

const circle = new Shape();
circle.type = "圆形";
console.log(circle.getInfo()); // 输出:类型:圆形

继承中的 this

当子类继承父类原型方法时:

javascript
function Square() {}
Square.prototype = Object.create(Shape.prototype); // 继承 Shape
const square = new Square();
square.type = "正方形";
console.log(square.getInfo()); // 输出:类型:正方形

2.5. 🌟 箭头函数的 this 上下文

箭头函数没有自己的 this,它继承外层函数的 this 值。

javascript
const obj = {
  name: "箭头函数示例",
  handler: () => {
    console.log(this.name); // 继承外层(全局)的 this,输出:undefined(严格模式下)
  }
};

obj.handler(); // 问题!

陷阱对比

类型是否拥有自己的 thisthis 绑定时机
普通函数运行时(调用时)
箭头函数定义时(外层 this)

正确使用箭头函数

javascript
const obj = {
  name: "正确写法",
  handler: function() {
    setTimeout(() => {
      console.log(this.name); // this 指向 obj
    }, 1000);
  }
};

知识回顾

  1. this 的核心作用:指向当前操作对象
  2. 绑定规则
    • 普通方法:指向调用该方法的对象
    • 构造函数:指向新创建的实例
    • 箭头函数:继承外层 this(无绑定)
  3. 常见问题场景
    • 回调函数中丢失 this 上下文
    • 箭头函数在类方法中的误用
  4. 解决方案
    • 使用 bind() 显式绑定
    • 保存 self = this 中间变量
    • 合理使用箭头函数避免意外绑定

课后练习

  1. (单选)以下代码输出结果是什么?
javascript
const obj = {
  value: 42,
  getVal: () => console.log(this.value)
};
obj.getVal(); // 输出:
- A. 42
- B. undefined
- C. 报错
  1. (填空)在类方法中,通过______关键字访问实例属性;在箭头函数中,this 继承自______的作用域。

  2. (代码纠错)修复以下代码,使按钮点击后输出“点击了红色按钮”:

html
<button id="myBtn" style="background: red;">点击我</button>
<script>
document.getElementById("myBtn").addEventListener("click", function() {
  console.log("点击了" + this.style.backgroundColor + "按钮");
});
</script>
  1. (操作题)创建一个 Car 类:
    • 属性:brandspeed
    • 方法:accelerate() 提升速度并输出 this.brand + " 加速到 " + this.speed
    • 使用箭头函数实现 displayInfo() 方法,确保 this 正确指向实例。

备注: (1) 通过对比箭头函数与普通函数的 this 行为,强化核心概念 (2) 强调事件处理、异步函数等场景的 this 问题解决方案

Built by Vitepress | Apache 2.0 Licensed