04. JavaScript 中 this 指向的 7 种典型场景解析
1. 普通函数调用模式
在独立调用的普通函数中(非严格模式):
javascript
function showThis() {
console.log(this); // 指向 window/global
}
showThis(); // 浏览器环境输出 Window 对象
严格模式下的差异:
javascript
"use strict";
function strictThis() {
console.log(this); // undefined
}
strictThis();
2. 箭头函数特性
箭头函数的 this
继承自词法作用域:
javascript
const obj = {
value: 42,
regular: function() {
setTimeout(function() {
console.log(this.value); // undefined(普通函数)
}, 100);
},
arrow: function() {
setTimeout(() => {
console.log(this.value); // 42(继承外层函数 this)
}, 100);
}
};
obj.regular();
obj.arrow();
类属性中使用箭头函数的典型案例:
javascript
class Counter {
count = 0;
increment = () => {
this.count++; // 始终绑定实例
};
}
const counter = new Counter();
const btn = document.querySelector('button');
btn.addEventListener('click', counter.increment); // this 正确指向实例
3. 对象方法调用
当函数作为对象方法调用时:
javascript
const person = {
name: 'Alice',
greet: function() {
console.log(`Hello, ${this.name}!`);
}
};
person.greet(); // "Hello, Alice!"
const greetFn = person.greet;
greetFn(); // "Hello, undefined!"(丢失上下文)
4. 构造函数模式
使用 new
关键字时:
javascript
function Car(make) {
this.make = make;
console.log(this instanceof Car); // true
}
const myCar = new Car('Tesla');
5. 显式绑定方法
通过 call
/apply
/bind
改变指向:
javascript
function introduce(lang) {
console.log(`${this.name} codes in ${lang}`);
}
const dev1 = { name: 'Bob' };
const dev2 = { name: 'Eve' };
introduce.call(dev1, 'JavaScript'); // Bob codes in JavaScript
introduce.apply(dev2, ['Python']); // Eve codes in Python
const boundFn = introduce.bind(dev1);
boundFn('Java'); // Bob codes in Java
6. Class 语法中的表现
类方法与箭头函数的对比:
javascript
class Timer {
constructor() {
this.seconds = 0;
}
// 普通方法
start() {
setInterval(function() {
this.seconds++; // 错误的 this 指向
}, 1000);
}
// 正确解决方案 1:箭头函数
startFixed1() {
setInterval(() => {
this.seconds++; // 正确指向实例
}, 1000);
}
// 正确解决方案 2:bind
startFixed2() {
setInterval(function() {
this.seconds++;
}.bind(this), 1000);
}
}
const t = new Timer();
t.startFixed1();
静态方法中的 this
:
javascript
class MyClass {
static staticMethod() {
console.log(this === MyClass); // true
}
}
MyClass.staticMethod();
7. 事件处理函数
DOM 事件处理中的典型情况:
javascript
button.addEventListener('click', function() {
console.log(this); // 指向 button 元素
});
// 错误示范
button.addEventListener('click', () => {
console.log(this); // 继承外层 this(可能是 window)
});
判断 this
的流程图(Mermaid)
记忆公式
对于任意函数 f
的 this
指向,可以表示为:
掌握这些规则后,建议通过以下步骤分析:
- 查看函数调用方式
- 确认是否使用箭头函数
- 检查是否通过对象调用
- 查看是否存在显式绑定
- 最后判断默认绑定情况