什么?还没弄懂关键字this?一篇文章带你速通

markdown 复制代码
# JavaScript中`this`关键字的深度解析

`this`是JavaScript中最重要且容易混淆的概念之一,其值取决于**函数调用方式**而非定义位置。以下是全面解析:

## 一、全局上下文中的`this`
在全局执行环境(非严格模式)中,`this`指向全局对象(浏览器中为`window`):
```javascript
console.log(this === window); // true
a = 10;
console.log(this.a); // 10

严格模式 下全局thisundefined

javascript 复制代码
'use strict';
console.log(this); // undefined

二、函数调用中的this

1. 普通函数调用

非严格模式下指向全局对象:

javascript 复制代码
function showThis() {
  console.log(this); // window
}
showThis();

严格模式下为undefined

javascript 复制代码
function strictShow() {
  'use strict';
  console.log(this); // undefined
}

2. 对象方法调用

指向调用该方法的对象:

javascript 复制代码
const user = {
  name: 'Alice',
  greet() {
    console.log(`Hello, ${this.name}!`);
  }
};
user.greet(); // "Hello, Alice!"

3. 构造函数调用

指向新创建的实例:

javascript 复制代码
function Person(name) {
  this.name = name;
}
const bob = new Person('Bob');
console.log(bob.name); // "Bob"

三、显式绑定

通过call()/apply()/bind()强制指定this

javascript 复制代码
function introduce(lang) {
  console.log(`${this.name} codes in ${lang}`);
}

const dev = { name: 'Charlie' };
introduce.call(dev, 'JavaScript'); // "Charlie codes in JavaScript"
const boundFunc = introduce.bind(dev);
boundFunc('Python'); // "Charlie codes in Python"

四、箭头函数的this

继承外层作用域的this(词法作用域):

javascript 复制代码
const timer = {
  delay: 1000,
  start() {
    setTimeout(() => {
      console.log(this.delay); // 正确指向timer对象
    }, this.delay);
  }
};
timer.start();

五、DOM事件处理

指向触发事件的元素:

html 复制代码
<button onclick="console.log(this.tagName)">Click</button>
<!-- 输出 "BUTTON" -->

六、常见问题与解决方案

1. 回调函数丢失this

错误示例:

javascript 复制代码
const counter = {
  count: 0,
  increment() {
    setInterval(function() {
      this.count++; // this指向window!
    }, 1000);
  }
};

解决方案:

javascript 复制代码
// 方案1:箭头函数
setInterval(() => this.count++, 1000);

// 方案2:bind绑定
setInterval(function() {
  this.count++;
}.bind(this), 1000);

// 方案3:保存this引用
const self = this;
setInterval(function() {
  self.count++;
}, 1000);

2. 方法赋值导致this丢失

javascript 复制代码
const obj = {
  id: 'obj1',
  logId() { console.log(this.id) }
};
const fn = obj.logId;
fn(); // undefined(this指向全局)

总结表格

场景 this指向 示例
全局环境 全局对象(非严格模式) this === window
普通函数调用 全局对象/undefined function() { console.log(this) }()
对象方法调用 调用对象 obj.method()
构造函数 新创建的实例 new Constructor()
箭头函数 外层作用域的this () => { console.log(this) }
事件处理器 触发事件的DOM元素 elem.onclick = function() { console.log(this) }
显式绑定 绑定的对象 func.call(ctx)

理解this的关键在于分析函数的调用方式,而非定义位置。

相关推荐
不听话坏19 分钟前
Ignition篇(下 一) 动态执行前的事情
开发语言·前端·javascript
likeyi0729 分钟前
require 和 import的区别
开发语言·前端
pany1 小时前
做 AI 友好的开源 Vue3 模板 🌈
前端·vue.js·ai编程
小二·1 小时前
React 19 + Next.js 15 现代前端开发实战:App Router / Server Components / 流式渲染
前端·javascript·react.js
谙忆10243 小时前
前端图片直传对象存储:OSS/S3 预签名 URL、STS 临时凭证与回调校验
前端
CHNE_TAO_EMSM4 小时前
Android studio 打开文件时自动下载源码
前端·javascript·android studio
一孤程4 小时前
Airtest自动化测试第五篇:小程序与Web测试——跨平台自动化全覆盖
前端·自动化测试·小程序·自动化·测试·airtest
IT_陈寒4 小时前
SpringBoot自动配置不是你以为的那样的智能
前端·人工智能·后端
yume_sibai5 小时前
大屏数据可视化 - 边框红绿呼吸灯实现详解
前端·信息可视化·typescript
竹林8186 小时前
从 ethers.js 迁移到 Viem:一个签名验证 Bug 让我彻底放弃旧爱
javascript