JS this 关键字
理解 this 在不同上下文中的指向 · 难度:进阶 · +15XP
JavaScript this 关键字详解
this 是 JavaScript 中最令人困惑的概念之一。它是一个特殊的关键字,在函数调用时自动定义,指向函数执行的上下文对象。this 的值不是在定义时确定的,而是在函数被调用时确定的,取决于函数的调用方式。
this 四种绑定规则
| 绑定方式 | this 指向 | 示例 |
|---|---|---|
| 默认绑定 | window / globalThis(严格模式为 undefined) | foo() |
| 隐式绑定 | 调用函数的对象 | obj.foo() |
| 显式绑定 | call/apply/bind 指定的对象 | foo.call(obj) |
| new 绑定 | 新创建的实例对象 | new Foo() |
| 箭头函数 | 定义时的外层 this(词法绑定) | () => this |
四种绑定规则详解
- 默认绑定:直接调用函数,非严格模式下 this 指向全局对象
- 隐式绑定:通过对象调用方法,this 指向该对象
- 显式绑定:使用 call/apply/bind 手动指定 this
- new 绑定:通过 new 调用构造函数,this 指向新实例
// 1. 默认绑定
function showThis() {
console.log(this);
}
showThis(); // window(浏览器)/ global(Node); 严格模式下为 undefined
// 2. 隐式绑定
const user = {
name: "张三",
greet() {
console.log("你好," + this.name);
}
};
user.greet(); // "你好,张三" (this = user)
// 注意:隐式丢失!
const fn = user.greet;
fn(); // "你好,undefined" (this = window,丢失了对象绑定)
// 3. 显式绑定: call / apply / bind
function introduce(age, city) {
console.log(this.name + "," + age + "岁,来自" + city);
}
const person = { name: "李四" };
introduce.call(person, 25, "北京"); // 李四,25岁,来自北京
introduce.apply(person, [30, "上海"]); // 李四,30岁,来自上海
const boundFn = introduce.bind(person, 28);
boundFn("深圳"); // 李四,28岁,来自深圳
// 4. new 绑定
function Person(name) {
this.name = name; // this 指向新创建的实例
}
const p = new Person("王五");
console.log(p.name); // "王五"
箭头函数与 this
// 箭头函数:this 从外层作用域继承(词法绑定)
const obj = {
name: "对象",
// 普通函数
normalFunc: function() {
console.log("normal:", this.name); // "对象"
// 箭头函数继承外层 this
const arrow = () => {
console.log("arrow:", this.name); // "对象"
};
arrow();
// 对比:如果用普通函数,this 会丢失
setTimeout(function() {
console.log("setTimeout normal:", this.name); // undefined
}, 100);
setTimeout(() => {
console.log("setTimeout arrow:", this.name); // "对象"
}, 100);
}
};
obj.normalFunc();
// 常见陷阱:事件处理中的 this
document.getElementById("btn").onclick = function() {
console.log(this); // 指向被点击的按钮元素
};
document.getElementById("btn").onclick = () => {
console.log(this); // 指向外层作用域(window),不是按钮!
};