JS中的 that = this

本文深入解析JavaScript中的this关键字,探讨其在不同上下文中的行为变化,以及如何通过var that = this来保持对原始对象的引用,避免因this作用域改变而导致的问题。

在JavaScript中,this代表的是当前对象。
this 是JavaScript语言的一个关键字。它代表函数运行时,自动生成一个内部对象,只能在函数内部使用

var that = this 就是将当前的this对象复制一份到that变量中,这样做有什么意义呢?

$(‘#conten').click(function(){
//this是被点击的#conten
var that = this;
$(.conten').each(function(){
//this是.conten循环中当前的对象
//that仍然是刚才被点击的#conten
});
});

这可以清楚的看到,this对象在程序中会随时的改变,而 var that = this 之后,that没改变之前仍然是指向当时的this,这样就不会出现找不到原来的对象。

<think>我们正在讨论JavaScript中的`let that = this`模式。这种模式用于解决在嵌套函数或回调函数中`this`指向改变的问题。在JavaScript中,`this`的值取决于函数被调用的方式,而不是定义的位置。因此,在内部函数中,`this`可能会指向全局对象(在非严格模式下)或`undefined`(在严格模式下),而不是外层函数的`this`。通过在外层函数中将`this`赋值给一个变量(通常命名为`that`, `self`或`_this`),内部函数可以通过该变量访问到外层的`this`。 ### 核心概念解析 1. **`this`的动态绑定**:JavaScript中的`this`是在运行时绑定,其值由函数的调用方式决定。常见情况包括: - 作为对象方法调用:`this`指向该对象。 - 作为普通函数调用:非严格模式下`this`指向全局对象(浏览器中为`window`),严格模式下为`undefined`。 - 作为构造函数调用:`this`指向新创建的对象。 - 使用`call`、`apply`、`bind`调用:`this`指向指定的对象。 2. **作用域链与闭包**:内部函数可以访问外部函数的变量,利用这一特性,将外部函数的`this`保存在变量中,内部函数通过闭包访问该变量。 ### 典型应用场景 #### 场景1:事件处理程序 ```javascript function MyComponent() { this.count = 0; const button = document.getElementById('myButton'); // 保存外部this的引用 const that = this; button.addEventListener('click', function() { // 内部函数中this指向触发事件的元素(button) that.count++; // 通过that访问外部this console.log(that.count); }); } const comp = new MyComponent(); ``` #### 场景2:异步回调(如`setTimeout`) ```javascript function Timer() { this.seconds = 0; const that = this; setInterval(function() { that.seconds++; console.log(that.seconds); }, 1000); } const timer = new Timer(); ``` #### 场景3:模块方法中的嵌套函数 ```javascript const module = { value: 42, getValue: function() { const that = this; function inner() { // 内部函数this指向全局对象,但通过that访问module return that.value; } return inner(); } }; console.log(module.getValue()); // 42 ``` ### 替代方案:箭头函数 ES6引入的箭头函数不绑定自己的`this`,而是继承外层作用域的`this`值。因此,在需要保留外层`this`的场景中,使用箭头函数可避免`that = this`模式: ```javascript function Timer() { this.seconds = 0; setInterval(() => { this.seconds++; // 直接使用外层this console.log(this.seconds); }, 1000); } ``` ### 注意事项 1. **变量命名约定**:常用`that`、`self`或`_this`保存`this`引用,需保持团队一致性。 2. **严格模式影响**:严格模式下普通函数的`this`为`undefined`,避免意外指向全局对象。 3. **内存泄漏风险**:闭包可能阻止垃圾回收,确保不再需要的引用及时释放。 ### 总结 `let that = this`是JavaScript中解决`this`指向问题的经典模式,通过闭包机制使嵌套函数访问正确的上下文。随着ES6的普及,箭头函数提供了更简洁的替代方案,但在维护旧代码或特定场景(如需要动态`this`的函数)中,该模式仍具实用价值。 §§相关问题§§ 1. 箭头函数如何处理`this`绑定? 2. 如何避免闭包导致的内存泄漏? 3. 严格模式对`this`绑定有哪些影响? </think>### JavaScript 中 `let that = this` 的含义、用途及相关知识 #### 一、核心概念 在 JavaScript 中,`this` 是一个**动态绑定的上下文对象**,其值取决于函数调用方式而非定义位置[^2]。当遇到嵌套函数或异步回调时,内部函数的 `this` 会丢失外层上下文: ```javascript class Example { constructor() { this.value = 10; setTimeout(function() { console.log(this.value); // 输出 undefined(this 指向全局对象) }, 100); } } ``` `let that = this` 模式通过**闭包机制**捕获当前上下文的 `this`: ```javascript class Example { constructor() { this.value = 10; const that = this; // 锁定当前 this setTimeout(function() { console.log(that.value); // 正确输出 10 }, 100); } } ``` #### 二、核心用途 1. **解决异步回调的上下文丢失** 在 Promise、setTimeout 等异步操作中保留原始对象: ```javascript function fetchData() { this.loading = true; const that = this; fetch('/api').then(function() { that.loading = false; // 正确修改原始对象 }); } ``` 2. **维护事件处理程序的上下文** 防止 DOM 事件中 `this` 指向触发元素而非组件实例: ```javascript class Button { handleClick() { const that = this; document.getElementById('btn').addEventListener('click', function() { that.logEvent(); // 而非 this.logEvent() }); } logEvent() { console.log('Clicked') } } ``` 3. **避免多层嵌套中的上下文混淆** 在嵌套函数链中传递原始上下文: ```javascript const obj = { value: 1, outer() { const that = this; function inner() { console.log(that.value); // 正确访问 obj.value } inner(); } }; ``` #### 三、技术原理 1. **词法作用域与闭包** `that` 变量被**内层函数闭包捕获**,形成持久引用链。即使外层函数执行完毕,内层函数仍可通过闭包访问 `that`[^3]。 2. **`this` 的动态绑定规则** | 调用方式 | `this` 指向 | 是否需 `that` | |-------------------|----------------------|----------------| | 对象方法调用 | 调用对象 | ❌ | | 普通函数调用 | 全局对象/`undefined` | ✔️ | | 构造函数调用 | 新创建实例 | ❌ | | DOM 事件处理 | 触发事件的元素 | ✔️ | | 箭头函数 | 继承外层 `this` | ❌ | #### 四、现代替代方案 1. **箭头函数(ES6+)** 自动继承外层 `this`,无需 `that`: ```javascript class Example { constructor() { this.value = 10; setTimeout(() => { console.log(this.value); // 自动绑定正确 this }, 100); } } ``` 2. **`bind()` 方法** 显式绑定上下文: ```javascript document.getElementById('btn').addEventListener( 'click', this.handleClick.bind(this) // 强制绑定 this ); ``` 3. **类字段语法(ES2022+)** 使用箭头函数类字段: ```javascript class Button { handleClick = () => { // 自动绑定实例 console.log(this); }; } ``` #### 五、最佳实践 1. **优先使用箭头函数** 在支持 ES6 的环境中,箭头函数是首选解决方案。 2. **必要时使用 `that`** 在以下场景仍需 `that`: - 维护旧代码兼容性 - 需要动态切换上下文时 ```javascript function dynamicContext(fn) { const that = this; return function(...args) { // 可在此处动态修改 that return fn.apply(that, args); }; } ``` 3. **避免内存泄漏** 及时移除事件监听,防止闭包长期持有对象引用: ```javascript class Component { init() { this._handler = () => this.doSomething(); element.addEventListener('click', this._handler); } destroy() { element.removeEventListener('click', this._handler); // 关键 } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值