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
) - 严格模式:如果函数无明确绑定对象,则
this
为undefined
挑战题:为什么输出是 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
常见错误场景
- 回调函数(如
setTimeout
、事件监听器) - 提取方法为独立函数
- 通过
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(); // 问题!
陷阱对比
类型 | 是否拥有自己的 this | this 绑定时机 |
---|---|---|
普通函数 | 是 | 运行时(调用时) |
箭头函数 | 否 | 定义时(外层 this) |
正确使用箭头函数
javascript
const obj = {
name: "正确写法",
handler: function() {
setTimeout(() => {
console.log(this.name); // this 指向 obj
}, 1000);
}
};
知识回顾
- this 的核心作用:指向当前操作对象
- 绑定规则:
- 普通方法:指向调用该方法的对象
- 构造函数:指向新创建的实例
- 箭头函数:继承外层 this(无绑定)
- 常见问题场景:
- 回调函数中丢失 this 上下文
- 箭头函数在类方法中的误用
- 解决方案:
- 使用
bind()
显式绑定 - 保存
self = this
中间变量 - 合理使用箭头函数避免意外绑定
- 使用
课后练习
- (单选)以下代码输出结果是什么?
javascript
const obj = {
value: 42,
getVal: () => console.log(this.value)
};
obj.getVal(); // 输出:
- A. 42
- B. undefined
- C. 报错
(填空)在类方法中,通过______关键字访问实例属性;在箭头函数中,this 继承自______的作用域。
(代码纠错)修复以下代码,使按钮点击后输出“点击了红色按钮”:
html
<button id="myBtn" style="background: red;">点击我</button>
<script>
document.getElementById("myBtn").addEventListener("click", function() {
console.log("点击了" + this.style.backgroundColor + "按钮");
});
</script>
- (操作题)创建一个 Car 类:
- 属性:
brand
、speed
- 方法:
accelerate()
提升速度并输出this.brand + " 加速到 " + this.speed
- 使用箭头函数实现
displayInfo()
方法,确保 this 正确指向实例。
- 属性:
备注: (1) 通过对比箭头函数与普通函数的 this 行为,强化核心概念 (2) 强调事件处理、异步函数等场景的 this 问题解决方案