为什么要读这篇文章
在日常开发中,你是否遇到过这些困惑:
- 为什么同一个函数,在不同地方调用,this 指向完全不同?
- 箭头函数的 this 为什么"不听话"?
- 面试官问"this 的绑定规则优先级"时,如何系统回答?
this 是 JavaScript 中最容易被误解的概念之一。它不像其他语言那样简单地指向"当前对象",而是具有动态绑定的特性。掌握 this 的核心规则,不仅能让你写出更优雅的代码,还能在排查 bug 时快速定位问题。
本文收益:
- 掌握 this 的 4 种绑定规则及其优先级
- 理解常见场景下的 this 指向(事件监听、定时器、数组方法等)
- 学会手写 call/apply/bind 实现
- 建立完整的 this 知识体系,应对各种边界情况
一、this 的本质:动态绑定的执行上下文
1.1 什么是 this
this 是函数执行时指向"当前执行上下文"的对象引用。
这句话包含三个关键信息:
- 执行时确定:this 的值在函数被调用时才确定,而非定义时
- 执行上下文:每次函数调用都会创建一个函数执行上下文(FEC),this 是其中的一个属性
- 动态绑定:同一个函数在不同调用方式下,this 可能指向不同对象
1.2 为什么需要 this
在面向对象编程中,Java、C++ 等语言的 this 通常只出现在类的实例方法中,指向当前实例。但 JavaScript 的 this 更加灵活,这种灵活性既是优势也是挑战。
使用 this 的核心价值:
javascript
// 不使用 this:代码耦合度高
var obj = {
name: "小吴",
eating: function() {
console.log(obj.name + "在吃东西");
},
running: function() {
console.log(obj.name + "在跑步");
}
}
// 使用 this:代码可复用性强
var obj = {
name: "小吴",
eating: function() {
console.log(this.name + "在吃东西");
},
running: function() {
console.log(this.name + "在跑步");
}
}
obj.eating() // 小吴在吃东西
obj.running() // 小吴在跑步
对比分析:
不使用 this 的问题:
- 方法内部硬编码了对象名称(obj.name)
- 无法复用方法到其他对象
- 对象重命名时需要修改所有方法内部代码
使用 this 的优势:
- 方法与具体对象解耦,提高可维护性
- 同一套方法可以被多个对象共享
- 符合面向对象的封装原则
1.3 全局作用域中的 this
在深入绑定规则前,先了解全局 this 的特殊性:
- 浏览器环境:this 指向 window 对象
- Node.js 环境:this 指向空对象 {}
javascript
// 浏览器环境
console.log(this === window); // true
// Node.js 环境
console.log(this); // {}
console.log(this === module.exports); // true
console.log(this === global); // false
Node.js 中的特殊机制:
Node.js 将每个文件视为一个模块,执行时会包装成如下形式:
javascript
(function(exports, require, module, __filename, __dirname) {
// 你的模块代码
// 顶层 this 被绑定到 module.exports
});
这就是为什么 Node.js 模块顶层的 this 指向 module.exports(初始为空对象),而非 global 对象。
函数内部的 this:
javascript
function foo() {
console.log(this);
}
foo.apply("小吴"); // [String: '小吴']
文件被 Node 执行时,会调用 foo.apply({}),将空对象传入作为 this。
1.4 同一函数,不同 this
这是理解 this 的关键案例:
javascript
function foo() {
console.log(this);
}
// 1. 直接调用
foo() // window(浏览器)或 global(Node.js 非严格模式)
// 2. 对象方法调用
var obj = {
name: "小吴",
foo: foo
}
obj.foo() // { name: '小吴', foo: [Function: foo] }
// 3. 显式绑定
foo.apply("XiaoWu") // [String: 'XiaoWu']

** 图8-3 函数的三种调用方式效果**
核心结论:
- this 的绑定与函数定义位置无关
- this 的绑定与函数调用方式和调用位置有关
- this 是在运行时动态绑定的
执行上下文中的 this:

** 图8-4 函数调用内存图**
在函数执行上下文(FEC)中,除了作用域链、变量对象(AO)等,还包含 this 绑定。
二、this 的四种绑定规则
掌握 this 的核心在于理解这四种绑定规则。只有显式绑定可以人为改变 this 指向,其他三种规则的 this 指向是固定的。
2.1 规则一:默认绑定
适用场景:独立函数调用(函数没有被绑定到任何对象上)
绑定结果:
- 非严格模式:指向全局对象(浏览器为 window,Node.js 为 global)
- 严格模式:指向 undefined
案例 1:最基础的独立调用
javascript
function foo() {
console.log(this);
}
foo() // window(浏览器)
案例 2:函数调用链中的独立调用
javascript
function foo1() {
console.log("foo1", this);
}
function foo2() {
console.log("foo2", this);
foo1()
}
function foo3() {
console.log("foo3", this);
foo2()
}
foo3()
// 输出:
// foo3 window
// foo2 window
// foo1 window

** 图8-5 案例2代码结果**
虽然函数之间有调用关系,但每个函数都是独立调用的,因此 this 都指向 window。
案例 3:对象方法赋值后的独立调用
javascript
var obj = {
name: "小吴",
foo: function() {
console.log(this);
}
}
var fn = obj.foo
fn() // window
关键理解:this 指向与函数定义位置无关,只与调用方式有关。虽然 foo 定义在 obj 中,但 fn() 是独立调用,因此 this 指向 window。
案例 4:函数引用的独立调用
javascript
function foo() {
console.log(this);
}
var obj = {
name: "小吴",
foo: foo
}
var bar = obj.foo
bar() // window
与案例 3 本质相同,bar 获取的是函数引用,调用时是独立调用。
案例 5:闭包中的独立调用
javascript
function foo() {
function bar() {
console.log(this);
}
return bar
}
var fn = foo()
fn() // window
// 改变调用方式后
var obj = {
name: "why",
age: fn
}
obj.age() // { name: 'why', age: [Function: bar] }
闭包函数的 this 不是固定指向 window,而是取决于调用方式。这打破了"闭包必定指向 window"的误解。
小结:
- 默认绑定的判断标准:函数是否独立调用(没有通过对象调用,没有使用 call/apply/bind,没有使用 new)
- 独立调用的 this 指向全局对象(非严格模式)或 undefined(严格模式)
- 函数定义位置不影响 this,只有调用方式才影响
2.2 规则二:隐式绑定
适用场景:通过对象调用方法(obj.method())
绑定结果:this 指向调用该方法的对象
核心原则:哪个对象发起的方法调用,this 就指向谁。
案例 1:基础隐式绑定
javascript
function foo() {
console.log(this);
}
var obj = {
name: "why",
foo: foo
}
obj.foo() // { name: 'why', foo: [Function: foo] }

** 图8-6 隐式绑定案例1效果图**
JavaScript 引擎会将 obj 对象绑定到 foo 函数的 this 中。
案例 2:方法中使用 this
javascript
var obj = {
name: "小吴",
eating: function() {
console.log(this.name + "在吃东西");
},
running: function() {
console.log(this.name + "在跑步");
}
}
obj.eating() // 小吴在吃东西
obj.running() // 小吴在跑步
// 解除绑定关系
var fn = obj.eating
fn() // undefined在吃东西(this.name 为 undefined)

** 图8-7 obj与eating绑定关系解除前后对比**
一旦解除对象与方法的绑定关系,this 指向就会改变。
案例 3:多层对象调用
javascript
var obj1 = {
name: "obj1",
foo: function() {
console.log(this);
}
}
var obj2 = {
name: "obj2",
bar: obj1.foo
}
obj2.bar() // { name: 'obj2', bar: [Function: foo] }

** 图8-8 案例3控制台打印结果**
虽然 bar 引用的是 obj1.foo,但调用时是通过 obj2 发起的,因此 this 指向 obj2。
小结:
- 隐式绑定的判断标准:函数是否通过对象调用(obj.method())
- this 指向最后调用该方法的对象
- 赋值操作会丢失隐式绑定,转为默认绑定
2.3 规则三:显式绑定
适用场景:使用 call、apply、bind 方法主动指定 this
绑定结果:this 指向传入的第一个参数对象
隐式绑定是"被动"的,需要对象内部有函数引用才能绑定。显式绑定则是"主动"的,可以直接指定 this 指向。
2.3.1 call 和 apply 的使用
call 语法 :func.call(thisArg, arg1, arg2, ...) apply 语法 :func.apply(thisArg, [argsArray])
核心区别:参数传递方式不同
- call:参数逐个传递
- apply:参数以数组形式传递
javascript
function sum(num1, num2) {
console.log(num1 + num2, this)
}
sum.call("call", 20, 30) // 50 [String: 'call']
sum.apply("apply", [20, 30]) // 50 [String: 'apply']
与直接调用的区别:
javascript
function foo() {
console.log("函数被调用了", this);
}
var obj = {
name: "why"
}
foo() // window
foo.apply("小吴") // [String: '小吴']
foo.call(obj) // { name: 'why' }

** 图8-9 直接调用与apply、call调用的不同**
2.3.2 bind 的使用
当需要多次使用相同的 this 绑定时,bind 比 call/apply 更方便。
bind 语法 :func.bind(thisArg[, arg1[, arg2[, ...]]])
特点:
- 返回一个新函数,不会立即执行
- 新函数的 this 被永久绑定到指定对象
- 可以预设部分参数(柯里化)
javascript
function foo() {
console.log(this)
}
// 使用 call 需要重复传参
// foo.call("小吴")
// foo.call("小吴")
// foo.call("小吴")
// 使用 bind 只需绑定一次
var newFoo = foo.bind("小吴")
newFoo() // [String: '小吴']
newFoo() // [String: '小吴']
bind 的特殊性:
javascript
function foo() {
console.log(this)
}
var newFoo = foo.bind("小吴")
var bar = foo
console.log(bar === foo) // true
console.log(newFoo === foo) // false
bind 返回的是一个新函数,与原函数不是同一个引用。这证明 bind 不会修改原函数,而是创建一个新的绑定函数。
2.3.3 三者对比
| 方法 | 执行时机 | 参数形式 | 返回值 | 使用场景 |
|---|---|---|---|---|
| call | 立即执行 | 逐个传递 | 函数执行结果 | 一次性调用,参数较少 |
| apply | 立即执行 | 数组传递 | 函数执行结果 | 一次性调用,参数较多或动态参数 |
| bind | 不执行 | 逐个传递 | 新函数 | 需要多次调用或延迟执行 |
小结:
- 显式绑定可以主动改变 this 指向
- call/apply 立即执行,bind 返回新函数
- 显式绑定的优先级高于隐式绑定和默认绑定
2.4 规则四:new 绑定
适用场景:使用 new 关键字调用函数(构造函数)
绑定结果:this 指向新创建的对象
new 的执行过程:
- 创建一个全新的对象
- 将这个对象的原型指向构造函数的 prototype
- 将 this 绑定到这个新对象
- 执行构造函数代码
- 如果构造函数没有返回对象,则返回这个新对象
javascript
function Person(name, age) {
this.name = name
this.age = age
}
Person() // 普通调用,this 指向 window
var p1 = new Person("小吴", 20)
console.log(p1.name, p1.age) // 小吴 20
var p2 = new Person("why", 35)
console.log(p2.name, p2.age) // why 35

** 图8-10 正常调用与new调用区别**
使用 new 调用时,JavaScript 会创建一个新对象并将其绑定到函数的 this 上。
小结:
- new 绑定会创建新对象并绑定到 this
- 构造函数只是使用 new 调用的普通函数
- new 绑定的优先级高于隐式绑定
三、常见场景中的 this 分析
3.1 setTimeout 定时器
javascript
// 普通函数
setTimeout(function() {
console.log("普通函数的this", this); // window(浏览器)或 global(Node.js)
}, 1000)
// 箭头函数
setTimeout(() => {
console.log("箭头函数的this", this); // 取决于外层作用域
}, 2000)

** 图8-11 node环境下的结果**
原理:setTimeout 内部不会绑定特定的 this,回调函数是独立调用,因此遵循默认绑定规则。
3.2 DOM 事件监听
javascript
const boxDiv = document.querySelector(".box")
// 方式1:onclick(只能绑定一个)
boxDiv.onclick = function() {
console.log(this); // boxDiv 元素对象
}
// 方式2:addEventListener(可以绑定多个)
boxDiv.addEventListener('click', function() {
console.log(this); // boxDiv 元素对象
})

** 图8-12 监听的对象**
原理 :浏览器内部会使用 fn.call(boxDiv) 的方式调用回调函数,将 DOM 元素绑定到 this。
3.3 数组高阶函数
javascript
var names = ["ABC", '小吴', 'why']
// 不传第二个参数
names.forEach(function(item) {
console.log("item", this); // window(三次)
})
// 传入第二个参数绑定 this
names.forEach(function(item) {
console.log("item", this); // [String: '小吴'](三次)
}, "小吴")

** 图8-13 forEach不加第二个参数**

** 图8-14 forEach加第二个参数**
常见数组方法的 this 绑定:
javascript
names.forEach(function() {
console.log("forEach", this);
}, "小吴")
names.map(function() {
console.log("map", this);
}, "小吴")
names.filter(function() {
console.log("filter", this);
}, "小吴")
names.find(function() {
console.log("find", this);
}, "小吴")

** 图8-16 forEach map filter find高阶函数对比情况**

** 图8-15 编辑器提供的语法提示**
实战建议:
- 大多数数组方法的最后一个参数用于绑定 this
- 使用 TypeScript 或现代编辑器可以看到参数提示
- 不需要死记硬背,看 API 文档或编辑器提示即可
四、this 绑定规则的优先级
当多个规则同时适用时,需要了解优先级来判断最终的 this 指向。
4.1 优先级排序
从高到低:new 绑定 > 显式绑定 > 隐式绑定> 默认绑定
4.2 优先级验证
1. 显式绑定 > 隐式绑定
javascript
var obj = {
name: "小吴",
foo: function() {
console.log(this);
}
}
obj.foo() // { name: '小吴', foo: [Function: foo] }
// call/apply 优先级更高
obj.foo.call("我是why") // [String: '我是why']
// bind 优先级更高
var bar = obj.foo.bind("小吴666")
bar() // [String: '小吴666']
更明显的对比:
javascript
function foo() {
console.log(this)
}
var obj1 = {
name: "这是bind更明显的比较",
foo: foo.bind("why")
}
obj1.foo() // [String: 'why']
虽然通过 obj1 调用(隐式绑定),但 foo 已经被 bind 绑定(显式绑定),最终 this 指向 "why"。
2. new 绑定 > 隐式绑定
javascript
var obj = {
name: "why的JS高级课程很不错,强烈推荐来看",
foo: function() {
console.log(this);
}
}
var f = new obj.foo() // foo {}
obj.foo() // { name: '...', foo: [Function: foo] }

** 图8-17 new绑定优先级高于隐式绑定**
3. new 绑定 > 显式绑定(bind)
注意:new 不能与 call/apply 一起使用(都是立即调用函数),只能与 bind 比较。
javascript
function foo() {
console.log(this);
}
var bar = foo.bind("测试一下")
bar() // [String: '测试一下']
var obj = new bar() // foo {}
new 调用时会找到原函数(foo),将其作为构造函数,创建新对象并绑定到 this。
4.3 优先级总结表
| 绑定类型 | 描述 | 优先级 | 判断方式 |
|---|---|---|---|
| new 绑定 | 使用 new 关键字调用 | 最高 | new func() |
| 显式绑定 | call/apply/bind | 中高 | func.call(obj) |
| 隐式绑定 | 对象方法调用 | 中低 | obj.func() |
| 默认绑定 | 独立函数调用 | 最低 | func() |
记忆技巧:越主动的绑定方式,优先级越高。
五、特殊情况与边界处理
5.1 忽略显式绑定
当 call/apply/bind 传入 null 或 undefined 时,会被忽略,应用默认绑定规则。
javascript
function foo() {
console.log(this);
}
foo() // window
foo.apply(null) // window
foo.apply(undefined) // window
使用场景:
- 不关心 this 指向,只想使用 apply 传递数组参数
- 使用 bind 进行柯里化,不需要绑定 this
安全实践 :传入空对象 Object.create(null) 代替 null,避免意外修改全局对象。
5.2 间接函数引用
赋值表达式返回的是函数引用,调用时属于独立调用。
javascript
var obj1 = {
name: "obj1",
foo: function() {
console.log(this);
}
}
var obj2 = {
name: "obj2"
}
obj2.foo = obj1.foo
obj2.foo() // { name: 'obj2', foo: [Function: foo] }
// 间接引用
(obj2.foo = obj1.foo)() // window
(obj2.foo = obj1.foo) 返回函数引用,然后立即调用,属于独立调用。
代码规范提醒:
javascript
var obj2 = {
name: "obj2"
}
(obj2.foo = obj1.foo)()
// 如果 obj2 后面没有分号,会被解析为:
// var obj2 = { name: "obj2" }(obj2.foo = obj1.foo)()
// 导致错误
解决方案:在对象字面量后加分号,或使用 ESLint 等工具强制规范。
5.3 经典测试题
javascript
function foo(el) {
console.log(el, this);
}
var obj = {
id: "XiaoWu"
};
[1, 2, 3].forEach(foo, obj)
// 报错:Uncaught TypeError: Cannot read properties of undefined
问题原因 :JavaScript 解析器将 [1,2,3] 解释为访问 obj 的属性。
解决方案:
javascript
// 方案1:使用变量
var names = [1, 2, 3]
names.forEach(foo, obj)
// 方案2:在 obj 后加分号
var obj = {
id: "XiaoWu"
};
[1, 2, 3].forEach(foo, obj)
这是 JavaScript 自动分号插入(ASI)机制的经典陷阱。
六、实战应用与最佳实践
6.1 判断 this 的决策树
在实际开发中,按以下顺序判断 this 指向:
javascript
1. 函数是否使用 new 调用?
→ 是:this 指向新创建的对象
2. 函数是否通过 call/apply/bind 调用?
→ 是:this 指向传入的第一个参数(null/undefined 除外)
3. 函数是否通过对象调用(obj.method())?
→ 是:this 指向该对象
4. 以上都不是?
→ 默认绑定:非严格模式指向全局对象,严格模式为 undefined
6.2 常见陷阱与解决方案
陷阱 1:事件回调中丢失 this
javascript
class Button {
constructor(text) {
this.text = text
}
handleClick() {
console.log(this.text)
}
}
const btn = new Button("点击我")
document.querySelector(".btn").addEventListener('click', btn.handleClick)
// 点击后输出 undefined,因为 this 指向 DOM 元素
解决方案:
javascript
// 方案1:使用 bind
document.querySelector(".btn").addEventListener('click', btn.handleClick.bind(btn))
// 方案2:使用箭头函数
document.querySelector(".btn").addEventListener('click', () => btn.handleClick())
// 方案3:在构造函数中绑定
class Button {
constructor(text) {
this.text = text
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
console.log(this.text)
}
}
陷阱 2:定时器中的 this
javascript
var obj = {
name: "小吴",
delayLog: function() {
setTimeout(function() {
console.log(this.name) // undefined
}, 1000)
}
}
obj.delayLog()
解决方案:
javascript
// 方案1:保存 this 引用
delayLog: function() {
var self = this
setTimeout(function() {
console.log(self.name) // 小吴
}, 1000)
}
// 方案2:使用箭头函数(推荐)
delayLog: function() {
setTimeout(() => {
console.log(this.name) // 小吴
}, 1000)
}
// 方案3:使用 bind
delayLog: function() {
setTimeout(function() {
console.log(this.name) // 小吴
}.bind(this), 1000)
}
陷阱 3:数组方法中的 this
javascript
var obj = {
name: "小吴",
friends: ["张三", "李四"],
printFriends: function() {
this.friends.forEach(function(friend) {
console.log(this.name + "的朋友:" + friend)
// undefined的朋友:张三
// undefined的朋友:李四
})
}
}
解决方案:
javascript
// 方案1:传入 thisArg 参数
printFriends: function() {
this.friends.forEach(function(friend) {
console.log(this.name + "的朋友:" + friend)
}, this)
}
// 方案2:使用箭头函数(推荐)
printFriends: function() {
this.friends.forEach(friend => {
console.log(this.name + "的朋友:" + friend)
})
}
6.3 团队协作规范建议
1. 代码审查检查点:
- 事件监听器是否正确绑定 this
- 定时器回调是否需要保持 this 上下文
- 数组方法回调是否需要访问外层 this
2. 编码规范:
- 优先使用箭头函数处理回调中的 this 问题
- 避免在构造函数外使用 bind,影响性能
- 对象字面量后统一加分号,避免 ASI 陷阱
3. TypeScript 辅助:
typescript
class Component {
name: string = "组件"
// 使用箭头函数属性,自动绑定 this
handleClick = () => {
console.log(this.name)
}
}
6.4 性能优化建议
bind 的性能开销:
javascript
// ❌ 不推荐:每次渲染都创建新函数
render() {
return <button onClick={this.handleClick.bind(this)}>点击</button>
}
// ✅ 推荐:在构造函数中绑定一次
constructor() {
this.handleClick = this.handleClick.bind(this)
}
// ✅ 推荐:使用箭头函数属性
handleClick = () => {
// ...
}
call/apply 的选择:
- 参数少于 3 个:使用 call(性能略优)
- 参数多或动态参数:使用 apply
- 需要多次调用:使用 bind
七、总结与进阶路线
7.1 核心要点回顾
this 的本质:
- this 是函数执行时的上下文对象引用
- 在函数调用时动态绑定,与定义位置无关
- 不同调用方式决定不同的 this 指向
四种绑定规则:
- 默认绑定:独立调用 → 全局对象或 undefined
- 隐式绑定:对象方法调用 → 调用对象
- 显式绑定:call/apply/bind → 指定对象
- new 绑定:构造函数调用 → 新创建的对象
优先级:new > 显式 > 隐式 > 默认
特殊情况:
- null/undefined 会被忽略,应用默认绑定
- 间接引用会导致默认绑定
- 箭头函数不遵循这些规则(继承外层作用域的 this)
7.2 团队落地建议
阶段一:知识普及(1-2 周)
- 组织内部分享会,讲解 this 的四种规则
- 整理常见陷阱案例库,供团队参考
- 在代码审查中重点关注 this 相关问题
阶段二:规范制定(1 周)
- 制定团队编码规范(箭头函数使用场景、bind 使用时机等)
- 配置 ESLint 规则,自动检测潜在问题
- 建立 this 相关的最佳实践文档
阶段三:工具支持(持续)
- 引入 TypeScript,利用类型系统减少 this 错误
- 使用现代框架(React Hooks、Vue 3 Composition API)减少 this 依赖
- 建立单元测试覆盖 this 相关逻辑
阶段四:持续优化(持续)
- 定期回顾 this 相关 bug,总结经验
- 更新团队知识库,补充新的边界情况
- 在新人培训中加入 this 专题
7.3 进阶学习路线
下一步学习内容:
-
箭头函数深入
- 箭头函数为什么没有自己的 this
- 箭头函数的词法作用域绑定
- 箭头函数的使用场景与限制
-
手写实现
- 手写 call/apply/bind 方法
- 理解 arguments 对象
- 实现 new 操作符
-
原型与继承
- 原型链中的 this
- 继承模式中的 this 处理
- ES6 class 中的 this
-
框架中的 this
- React 中的 this 绑定策略
- Vue 中的 this 代理机制
- 现代框架如何减少 this 依赖
推荐资源:
- 《你不知道的 JavaScript(上卷)》第二部分
- MDN Web Docs - this 关键字
- JavaScript.info - 对象方法与 this
7.4 验证学习成果
自测题:
- 以下代码输出什么?为什么?
javascript
var name = "window"
var obj = {
name: "obj",
foo: function() {
return function() {
console.log(this.name)
}
}
}
obj.foo()()
- 如何让以下代码正确输出 "小吴"?
javascript
var obj = {
name: "小吴",
getName: function() {
setTimeout(function() {
console.log(this.name)
}, 1000)
}
}
obj.getName()
- 以下代码的优先级判断是否正确?
javascript
function foo() {
console.log(this)
}
var obj = {
foo: foo.bind("bind")
}
new obj.foo() // 输出什么?
答案与解析:
- 输出 "window"。obj.foo() 返回一个函数,然后独立调用,应用默认绑定。
- 使用箭头函数:
setTimeout(() => { console.log(this.name) }, 1000) - 输出
foo {}。new 绑定优先级高于显式绑定。
八、写在最后
this 是 JavaScript 中最具争议的特性之一。它的灵活性带来了强大的表达能力,但也增加了理解成本。
关键心态:
- 不要死记硬背,理解背后的执行机制
- 遇到问题时,按优先级逐一排查
- 善用工具(TypeScript、ESLint)减少错误
- 在现代开发中,考虑使用箭头函数或 Hooks 减少对 this 的依赖
实践建议:
- 在真实项目中刻意练习 this 的判断
- 遇到 bug 时,先检查 this 指向是否正确
- 代码审查时,关注 this 相关的潜在问题
- 定期回顾本文,加深理解
掌握 this 不是终点,而是深入理解 JavaScript 执行机制的起点。接下来,我们将探讨箭头函数、手写实现 call/apply/bind,以及原型链等更深入的话题。
持续学习,保持好奇心,我们下期见!