JavaScript中this的5大核心规则详解

在 JavaScript 中,this 是一个特殊关键字,其值取决于函数的 调用方式 而非定义位置。它的行为遵循一套明确的规则,以下是核心规则和示例:


1. 默认绑定(独立函数调用)

当函数独立调用时(不作为方法、构造函数等),this 指向全局对象:

  • 浏览器中window
  • Node.js 中global
function show() {console.log(this); // 浏览器:Window / Node.js:global
}
show(); // 独立调用

严格模式('use strict')下thisundefined


2. 隐式绑定(方法调用)

当函数作为对象方法调用时,this 指向 调用该方法的对象

const user = {name: "Alice",greet() {console.log(`Hello, ${this.name}!`);}
};
user.greet(); // "Hello, Alice!"(this = user)

⚠️ 易错点:绑定丢失
若将方法赋值给变量后调用,会丢失原始绑定,退回到默认绑定:

const greet = user.greet;
greet(); // "Hello, undefined!"(this 指向全局)

3. 显式绑定(call / apply / bind)

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

function greet() {console.log(`Hello, ${this.name}!`);
}const alice = { name: "Alice" };
const bob = { name: "Bob" };// call/apply 立即调用
greet.call(alice); // "Hello, Alice!"(this = alice)
greet.apply(bob);  // "Hello, Bob!"(this = bob)// bind 创建新函数(永久绑定)
const boundGreet = greet.bind(alice);
boundGreet(); // "Hello, Alice!"

4. new 绑定(构造函数)

使用 new 调用构造函数时,this 指向 新创建的对象

function Person(name) {this.name = name; // this = 新对象
}
const alice = new Person("Alice");
console.log(alice.name); // "Alice"

5. 箭头函数:词法作用域绑定

箭头函数 没有自己的 this,它会继承外层作用域的 this(定义时绑定,非调用时):

const user = {name: "Alice",greet: function() {// 普通函数:this = usersetTimeout(() => {console.log(`Hello, ${this.name}!`); // this 继承自 greet}, 100);}
};
user.greet(); // "Hello, Alice!"(箭头函数捕获了 user)

⚠️ 注意

  • 箭头函数的 this 不可通过 call/bind 修改。
  • 对象字面量、类中的箭头函数会绑定到外层作用域(可能是全局)。

特殊场景总结

场景this 指向示例
独立函数调用全局对象(严格模式为 undefinedfunc()
对象方法调用调用该方法的对象obj.method()
call/apply/bind显式指定的对象func.call(ctx)
new 构造函数新创建的对象实例new Constructor()
箭头函数外层词法作用域的 this() => { ... }
DOM 事件处理触发事件的元素button.onclick = func

常见问题解决技巧

  1. 方法绑定丢失:用 bind() 或箭头函数固定 this

    // 方法1: bind
    const boundMethod = obj.method.bind(obj);
    // 方法2: 箭头函数
    obj.method = () => { ... };
    
  2. 回调函数中的 this

    • 使用箭头函数保留外层 this
    • 显式绑定:setTimeout(function() {...}.bind(this), 100)
  3. 类中的方法:使用箭头函数或手动绑定,避免丢失 this

    class Counter {count = 0;// 方案1: 类字段(箭头函数)increment = () => {this.count++;};// 方案2: 构造函数中绑定constructor() {this.decrement = this.decrement.bind(this);}decrement() {this.count--;}
    }
    

终极秘诀

this 的值在函数调用时确定,而非定义时。
始终问自己:这个函数是如何被调用的?

  • obj.func()this = obj
  • func()this = 全局/undefined
  • new Func()this = 新对象
  • 箭头函数 → 继承外层 this

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/2646.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度分析Java内存回收机制

内存回收机制是Java区别于C/C等语言的核心特性之一,也是Java开发者理解程序性能、解决内存相关问题(如内存泄漏、OOM)的关键。 核心目标: 自动回收程序中不再使用的对象所占用的内存,防止内存耗尽,同时尽量…

字节 AI 编辑器 Trae 2.0 SOLO 出道! 国际版不充分指南及与国内版的对比

最近 Trae 2.0 上线,带来了强势的 SOLO,一个能自主执行开发任务的超级个体,集成编辑器、终端、浏览器等多工具视图于一体,打通从构思到落地的完整链路。 不过国内版需要预约(饥饿营销?)&#x…

二分查找----3.在排序数组中查找元素的第一个和最后一个位置

题目链接 /** 在一个近似递增的数组中查找指定元素,该元素可能有多个找出其出现的区间 单次普通二分只能查到一个元素且无法确定边界;对二分改进即可 左边界:当查到目标元素时,记录下标并将right迭代为mid-1,继续向左二分直到搜寻结束,得到左边界 右边界:当查到目标元素时,记录…

修改 Lucide-React 图标样式的方法

修改 Lucide-React 图标样式的方法 使用 lucide-react 时&#xff0c;你可以通过多种方式修改图标的样式。以下是几种常用的方法&#xff1a; 1. 通过 className 属性 import { Home } from lucide-react;function MyComponent() {return <Home className"text-blue-50…

新手向:Idea的使用技巧

为什么选择IntelliJ IDEA作为Java开发工具&#xff1f; IntelliJ IDEA被誉为Java开发者的"智能助手"&#xff0c;它就像手机里的Siri或小爱同学一样&#xff0c;能够智能地辅助开发者完成各种编程任务。 具体来说&#xff0c;IDEA具有以下突出优势&#xff1a; 智…

自动化运维:从脚本到DevOps的演进

自动化通常从编写脚本开始&#xff0c;这些脚本可以自动执行常规任务&#xff0c;如备份数据、更新软件或监控系统性能。例如&#xff0c;一个简单的Bash脚本可以定期检查磁盘空间并清理临时文件&#xff1a;#!/bin/bash # Disk Cleanup Script threshold80 # Set threshold…

Python机器学习:从零基础到项目实战

目录第一部分&#xff1a;思想与基石——万法归宗&#xff0c;筑基问道第1章&#xff1a;初探智慧之境——机器学习世界观1.1 何为学习&#xff1f;从人类学习到机器智能1.2 机器学习的“前世今生”&#xff1a;一部思想与技术的演进史1.3 为何是Python&#xff1f;——数据科学…

【kubernetes】-2 K8S的资源管理

文章目录K8S的资源管理1、资源管理方式简介1.1 陈述式管理资源的方法1.2 kubernetes 集群资源管理入口2、kubectl 常用命令2.1 集群操作2.2 资源操作2.3 项目生命周期管理2.3.1 创建2.3.2 发布2.3.3 更新2.3.4 回滚2.3.5删除3、图解服务发布阶段 1&#xff1a;外部客户端 → 节…

AWS PrivateLink方式访问Redis

问题 现在有两个不同的aws云账号&#xff0c;而且&#xff0c;这两个不同云账号&#xff0c;其中一个拥有Redis服务&#xff08;elasticache&#xff09;。现在需要通过另外一个账号的vpc内网访问另外一个账号的内网的redis服务。 解决 AWS PrivateLink方式。这样就可以通过…

数据库—修改某字段默认值

前言有时候&#xff0c;数据库的字段默认值没有正确设置&#xff0c;这时候需要改默认值。以下是我做的改默认值的记录&#xff0c;希望对网友有所帮助。1.SQL SERVER下面的示例假设你要修改名为 YourColumnName 的字段&#xff0c;并为其设置一个新的默认值 NewDefaultValue。…

Go语言切片(Slice)与数组(Array)深度解析:避坑指南与最佳实践

在Go语言中&#xff0c;切片(slice)和数组(array)是两种基础但常被混淆的数据结构。本文将深入剖析它们的核心区别&#xff0c;揭示常见陷阱&#xff0c;并提供实战解决方案。一、本质区别&#xff1a;固定大小 vs 动态容器 数组(Array)&#xff1a;固定长度的连续内存块 // 声…

2025乐彩V8影视系统技术解析:双端原生架构与双H5免签封装实战 双端原生+双H5免签封装+TV级性能优化,一套代码打通全终端生态

1. 双端原生实现方案 Android端&#xff1a;基于Kotlin Jetpack Compose架构&#xff0c;深度优化ExoPlayer内核&#xff0c;支持4K HDR硬解与DRM加密流 iOS端&#xff1a;Swift SwiftUI构建&#xff0c;集成AVFoundation定制播放器&#xff0c;实现画中画与杜比全景声支持 …