0x01、内存模型
JavaScript 内存分为两部分:
栈(Stack):存储原始类型和执行上下文 堆(Heap):存储引用类型(对象、函数、数组)
示例:
let age = 30; // 原始类型 → 栈
const user = { name: "Alice" }; // 对象 → 堆
内存示意:
栈 (Stack) | 堆 (Heap)
---------------------------|----------------------------
全局执行上下文 |
- age: 30 |
- user: <地址 0x01> |
---------------------------|----------------------------
| 地址 0x01: { name: "Alice" }
0x02、执行上下文
在 JavaScript 中,this
不是静态的,而是动态绑定的。它的值在函数调用时确定,而不是在定义时。
理解 this
的关键在于理解 执行上下文(Execution Context)。
每个函数被调用时,都会创建一个新的执行上下文,其中包含:
Lexical Environment(词法环境,存储变量和函数) Variable Environment(用于 var
声明)this 绑定(当前上下文的核心属性)
内存结构示意:
栈 (Stack) | 堆 (Heap)
---------------------------|----------------------------
函数执行上下文 |
- LexicalEnv: { ... } |
- this: <指向的对象> |
-------------------------- |----------------------------
| 对象/函数存储在堆中
0x03、this 的 6 种绑定规则
1. 默认绑定(独立函数调用)
在独立函数调用中,this
的绑定规则是,在浏览器非严格模式下指向window
对象,严格模式下是 undefined
,如:
function show() {
console.log(this);
}
show(); // window 或者 undefined
[!info] ES5 引入的严格模式下,默认绑定不再指向全局对象,而是
undefined
。
ES2020 之后,推荐使用globalThis
来访问全局对象,它在浏览器、Node.js 等环境下统一。
内存示意:
栈 (Stack) | 堆 (Heap)
-----------------------------|----------------------------
show() 执行上下文 |
- this: <全局对象 或 undefined>|
-----------------------------|----------------------------
全局执行上下文 |
- show: <函数> |
-----------------------------|----------------------------
| 全局对象(window / globalThis)
2. 隐式绑定(方法调用)
在方法调用中,this
指向调用的对象,如:
const user = {
name: "Bob",
greet() {
console.log(`Hello, ${this.name}!`);
}
};
user.greet(); // "Hello, Bob!"
内存示意:
栈 (Stack) | 堆 (Heap)
------------------------|----------------------------
greet() 执行上下文 |
- this: <地址 0x01> |
------------------------|----------------------------
全局执行上下文 |
- user: <地址 0x01> |
------------------------|----------------------------
| 地址 0x01: {
| name: "Bob",
| greet: <函数>
| }
3. 显式绑定(call/apply/bind)
显式绑定的时候,this
指向显式绑定的对象,如:
function greet() {
console.log(`Hello, ${this.name}!`);
}
const alice = { name: "Alice" };
greet.call(alice); // "Hello, Alice!"
内存示意:
栈 (Stack) | 堆 (Heap)
---------------------------|----------------------------
greet() 执行上下文 |
- this: <地址 0x02> |
---------------------------|----------------------------
全局执行上下文 |
- alice: <地址 0x02> |
---------------------------|----------------------------
| 地址 0x02: { name: "Alice" }
4. new 绑定(构造函数)
通过 new
创建对象的时候,this
指向新创建的对象,如:
function User(name) {
this.name = name;
}
const bob = new User("Bob");
console.log(bob.name); // "Bob"
内存示意:
栈 (Stack) | 堆 (Heap)
---------------------------|----------------------------
User() 执行上下文 |
- this: <地址 0x03> |
---------------------------|----------------------------
全局执行上下文 |
- bob: <地址 0x03> |
---------------------------|----------------------------
| 地址 0x03: { name: "Bob" }
5. 箭头函数(词法绑定)
当使用箭头函数的时候,this
指向外层词法作用域的 this
,如:
const counter = {
count: 0,
increment() {
setTimeout(() => {
this.count++; // this 继承自 increment
}, 100);
}
};
counter.increment(); // 隐式绑定
内存示意:
栈 (Stack) | 堆 (Heap)
---------------------------|----------------------------
increment() 执行上下文 |
- this: <地址 0x04> |
---------------------------|----------------------------
setTimeout 回调(箭头函数) |
- [[This]]: <地址 0x04> |
---------------------------|----------------------------
全局执行上下文 |
- counter: <地址 0x04> |
---------------------------|----------------------------
| 地址 0x04: {
| count: 1,
| increment: <函数>
| }
6. class 中的 this
情况一:普通方法
普通方法的方法定义在原型上:
class User {
name = "Alice";
greet() {
console.log(`Hello, ${this.name}`);
}
}
const u = new User();
u.greet(); // Hello, Alice
const fn = u.greet;
fn(); // TypeError: Cannot read properties of undefined
内存示意:
栈 (Stack) | 堆 (Heap)
---------------------------|----------------------------
fn() 执行上下文 |
- this: undefined |
---------------------------|----------------------------
全局执行上下文 |
- u: <地址 0x01> |
- fn: <地址 0x02> |
---------------------------|----------------------------
| 地址 0x01: { name: "Alice" }
| User.prototype: { greet: <地址 0x02> }
| 地址 0x02: function greet() { ... }
情况二:箭头函数
箭头函数的方法定义为实例属性:
class User {
name = "Alice";
greet = () => { console.log(`Hello, ${this.name}`); }
}
const u = new User();
const fn = u.greet;
fn(); // "Hello, Alice"
内存示意:
栈 (Stack) | 堆 (Heap)
---------------------------|----------------------------
fn() 执行上下文 |
- this: <继承自外层作用域> |
---------------------------|----------------------------
全局执行上下文 |
- u: <地址 0x03> |
- fn: <地址 0x04> |
---------------------------|----------------------------
| 地址 0x03: {
| name: "Alice",
| greet: <地址 0x04>
| }
| 地址 0x04: () => { ... }
| [[This]]: 固定为 <地址 0x03>
0x04、this 与闭包的内存关系
闭包让函数能访问外层作用域的变量,但要注意箭头函数继承的 this
并不会自动绑定到返回对象。
错误示例:
function createCounter() {
let count = 0;
return {
increment: () => { count++; this.log(); },
log: () => console.log(count)
};
}
正确写法:
function createCounter() {
let count = 0;
return {
increment() { count++; this.log(); },
log() { console.log(count); }
};
}
0x05、常见问题与解决方案
问题 1:回调函数丢失 this
const user = {
name: "Alice",
greet() {
setTimeout(function() {
console.log(this.name); // undefined
}, 100);
}
};
解决方案:使用箭头函数
setTimeout(() => {
console.log(this.name); // "Alice"
}, 100);
问题 2:方法赋值丢失 this
const user = { name: "Alice", greet() { console.log(this.name); } };
const greet = user.greet;
greet(); // undefined
解决方案:bind
const boundGreet = user.greet.bind(user);
boundGreet(); // "Alice"
问题 3:嵌套函数丢失 this
const obj = {
value: 42,
getValue() {
function helper() {
return this.value; // undefined
}
return helper();
}
};
解决方案:箭头函数或变量保存
// 箭头函数
const helper = () => this.value;
// 变量保存
const self = this;
function helper() {
return self.value;
}
问题 4:模块中的 this
在 ES6 模块中,顶层 this === undefined
,而不是全局对象。
// module.js
console.log(this); // undefined
问题 5:事件监听中的 this
button.addEventListener("click", function() {
console.log(this); // button 元素
});
button.addEventListener("click", () => {
console.log(this); // 外层作用域(比如 window 或 class 实例)
});

优网科技秉承"专业团队、品质服务" 的经营理念,诚信务实的服务了近万家客户,成为众多世界500强、集团和上市公司的长期合作伙伴!
优网科技成立于2001年,擅长网站建设、网站与各类业务系统深度整合,致力于提供完善的企业互联网解决方案。优网科技提供PC端网站建设(品牌展示型、官方门户型、营销商务型、电子商务型、信息门户型、微信小程序定制开发、移动端应用(手机站、APP开发)、微信定制开发(微信官网、微信商城、企业微信)等一系列互联网应用服务。