10.JS 中的 this 究竟指向谁? 副本.md 来源:https://my.feishu.cn/file/GEHUbVZ7Zo39ZBxNRx8cQY39nTc 采集状态:已完成正文采集;原文件源码视图逐行采集,行号 1 至 135 连续,滚动到底。 ## 1\. 核心概念 (Core Concept) `this` 是 JavaScript 中的一个关键字,它在执行上下文中是一个特殊的对象引用。与词法作用域不同,`this` 的值是**在函数被调用时**才确定的(运行时绑定),而不是在函数定义时。它的指向完全取决于函数的**调用方式 (call-site)**。 ## 2\. 为什么需要理解 `this`? (The "Why") 1. **面向对象编程的基础**: 在基于原型和类的面向对象编程中,`this` 是访问实例属性和方法的关键。错误地理解 `this` 会导致无法正确地操作对象状态。 2. **解决常见的回调函数问题**: 在回调函数(如事件处理器、定时器)中,`this` 的指向常常会丢失,导致非预期的行为。理解 `this` 的绑定规则是解决这类问题的核心。 3. **掌握框架和库的原理**: 许多框架(如 React 的类组件)和库都大量使用 `this`。理解其工作原理有助于更深入地使用这些工具,并能解决相关问题。 4. **`this` 是面试高频题**: 对 `this` 指向的各种场景进行判断,是 JavaScript 面试中考察应聘者基础知识是否扎实的经典问题。 ## 3\. API 与用法 (API & Usage) `this` 的指向主要遵循以下几种规则,优先级从低到高排列: ### 1\. 默认绑定 (Default Binding) 当函数独立调用,且没有应用其他规则时,`this` 指向全局对象。在严格模式 (`'use strict'`) 下,`this` 为 `undefined`。 ```javascript function sayHi() { console.log(this); } sayHi(); // 非严格模式: Window 对象 // 严格模式: undefined ``` ### 2\. 隐式绑定 (Implicit Binding) 当函数作为对象的一个方法被调用时,`this` 指向调用该方法的对象。 ```javascript const user = { name: 'Alice', greet: function() { console.log(`Hello, ${this.name}`); } }; user.greet(); // "Hello, Alice"。greet() 被 user 对象调用,this 指向 user。 ``` **隐式丢失**: 如果将方法赋给一个变量后独立调用,`this` 会丢失其原始上下文。 ```javascript const standaloneGreet = user.greet; standaloneGreet(); // 非严格模式: "Hello, " (this 指向全局对象) // 严格模式: TypeError (this 是 undefined) ``` ### 3\. 显式绑定 (Explicit Binding) 通过 `call()`, `apply()`, 或 `bind()` 方法,可以**明确地**指定函数调用时的 `this` 值。 - **`call(thisArg, arg1, arg2, ...)`**: 立即调用函数,`this` 绑定到 `thisArg`,参数逐个传递。 - **`apply(thisArg, [argsArray])`**: 立即调用函数,`this` 绑定到 `thisArg`,参数以数组形式传递。 - **`bind(thisArg)`**: **不**立即调用函数,而是**返回**一个 `this` 被永久绑定到 `thisArg` 的新函数。 ```javascript function introduce(city, country) { console.log(`I am ${this.name} from ${city}, ${country}.`); } const person = { name: 'Bob' }; introduce.call(person, 'New York', 'USA'); // "I am Bob from New York, USA." introduce.apply(person, ['London', 'UK']); // "I am Bob from London, UK." const introduceBob = introduce.bind(person); introduceBob('Paris', 'France'); // "I am Bob from Paris, France." ``` ### 4\. `new` 绑定 (`new` Binding) 当使用 `new` 关键字调用一个函数(构造函数)时,会自动执行以下步骤: 1. 创建一个全新的空对象。 2. 这个新对象的 `[[Prototype]]` 被链接到构造函数的 `prototype`。 3. 这个新对象被绑定为函数调用的 `this`。 4. 如果函数没有返回其他对象,则 `new` 表达式会隐式返回这个新对象。 ```javascript function Person(name) { this.name = name; } const alice = new Person('Alice'); console.log(alice.name); // "Alice"。在 Person 调用中,this 指向新创建的 alice 对象。 ``` ### 箭头函数 (`=>`) 的 `this` 箭头函数**没有自己的 `this` 绑定**。它会捕获其定义时所在上下文(词法作用域)的 `this` 值。`this` 的值在箭头函数定义时就已经确定,且之后无法通过 `call`, `apply`, `bind` 修改。 ```javascript const obj = { name: 'My Object', regularMethod: function() { console.log(this.name); // 'My Object' // 箭头函数捕获了 regularMethod 的 this const arrowFunc = () => { console.log(this.name); }; arrowFunc(); // 'My Object' }, arrowMethod: () => { // 箭头函数在对象字面量中定义,捕获了定义时的全局 this console.log(this.name); } }; obj.regularMethod(); obj.arrowMethod(); // 非严格模式下是全局 name (e.g., ""), 严格模式下 this 是 undefined ``` ## 4\. 关键注意事项 (Key Considerations) 1. **优先级规则**: `new` 绑定 \> 显式绑定 (`bind`) \> 隐式绑定 \> 默认绑定。箭头函数的 `this` 不参与这个优先级比较,因为它在定义时就已固定。 2. **`bind` 的硬绑定**: `bind` 创建的新函数,其 `this` 无法被后续的 `call` 或 `apply` 修改(但 `new` 依然可以覆盖 `bind` 的绑定)。 3. **回调函数中的 `this` 丢失**: 在 `setTimeout`, 事件监听器等场景中,回调函数通常作为独立函数被调用,会触发默认绑定规则。这是箭头函数或 `.bind(this)` 最常见的应用场景。 4. **严格模式的影响**: 在严格模式下,默认绑定的 `this` 是 `undefined` 而不是全局对象,这有助于提早发现错误。 ## 5\. 参考资料 (References) - [MDN Web Docs: this](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this) - [MDN Web Docs: Arrow functions](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions) - [You Don't Know JS Yet: `this` & Object Prototypes](https://www.google.com/search?q=%5Bhttps://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/this-object-prototypes%5D\(https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/this-object-prototypes\)) - [ECMAScript® 2025 Language Specification: The this Keyword](https://www.google.com/search?q=https://tc39.es/ecma262/%23sec-this-keyword) 原文链接与附件索引 MDN Web Docs: this https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this MDN Web Docs: Arrow functions https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions You Don't Know JS Yet: `this` & Object Prototypes https://www.google.com/search?q=%5Bhttps://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/this-object-prototypes%5D\(https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/this-object-prototypes\ ECMAScript® 2025 Language Specification: The this Keyword https://www.google.com/search?q=https://tc39.es/ecma262/%23sec-this-keyword