什么?还没弄懂关键字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的关键在于分析函数的调用方式,而非定义位置。

相关推荐
脑袋大大的1 小时前
判断当前是否为钉钉环境
开发语言·前端·javascript·钉钉·企业应用开发
军军君011 小时前
基于Springboot+UniApp+Ai实现模拟面试小工具二:后端项目搭建
前端·javascript·spring boot·spring·微信小程序·前端框架·集成学习
quweiie2 小时前
tp8.0\jwt接口安全验证
前端·安全·jwt·thinkphp
xiaoyan20152 小时前
最新Flutter3.32+Dart3仿微信App聊天实例
前端·flutter·dart
汪敏wangmin2 小时前
Fiddler-抓包后直接生成Loadrunner脚本或者Jmeter脚本
前端·jmeter·fiddler
彤银浦3 小时前
Web学习笔记3
前端·笔记·学习·html5
江城开朗的豌豆3 小时前
退出登录后头像还在?这个缓存问题坑过多少前端!
前端·javascript·vue.js
江城开朗的豌豆3 小时前
Vue的'读心术':它怎么知道数据偷偷变了?
前端·javascript·vue.js
江城开朗的豌豆3 小时前
手把手教你造一个自己的v-model:原来双向绑定这么简单!
前端·javascript·vue.js
我在北京coding3 小时前
el-tree 懒加载 loadNode
前端·vue.js·elementui