深入解读 JavaScript 中 `this` 的指向机制:覆盖所有场景与底层原理

this 是 JavaScript 中最容易引发困惑的核心概念之一,它的指向在不同场景下呈现截然不同的行为。本文将系统性地解析 this 的所有使用场景,结合代码示例和底层原理,帮助你彻底掌握其运行机制。


一、全局环境下的 this

1. 浏览器环境
在浏览器全局作用域中,this 指向 window 对象:

console.log(this === window); // true (非严格模式)

2. Node.js 环境
在 Node.js 模块顶层作用域中,this 指向当前模块的 exports 对象:

console.log(this === module.exports); // true

底层原理
全局环境中的 this 由执行环境的全局对象决定,浏览器为 window,Node.js 模块中为 exports


二、函数调用中的 this

1. 独立函数调用(非严格模式)

function showThis() {console.log(this);
}
showThis(); // window (浏览器) / global (Node.js)

2. 严格模式下的函数调用

"use strict";
function strictThis() {console.log(this);
}
strictThis(); // undefined

底层原理
函数调用时,若未指定 this(即非方法调用、未使用 new 或绑定),非严格模式下 this 回退到全局对象;严格模式下保持为 undefined


三、对象方法中的 this

const obj = {name: "Alice",greet: function() {console.log(this.name);}
};
obj.greet(); // "Alice"

隐式丢失问题

const greet = obj.greet;
greet(); // undefined (严格模式下) 或 window.name (非严格模式)

原理分析
方法赋值给变量后,调用变为独立函数调用,this 丢失原始绑定。


四、构造函数中的 this

使用 new 调用构造函数时,this 指向新创建的实例:

function Person(name) {this.name = name;
}
const bob = new Person("Bob");
console.log(bob.name); // "Bob"

底层过程

  1. 创建空对象,其 [[Prototype]] 指向构造函数原型
  2. 构造函数内的 this 绑定到此新对象
  3. 若构造函数无显式返回,自动返回新对象

五、显式绑定:call/apply/bind

1. call & apply

function introduce(lang) {console.log(`${this.name} codes in ${lang}`);
}
const user = { name: "Charlie" };
introduce.call(user, "JavaScript"); // "Charlie codes in JavaScript"
introduce.apply(user, ["Python"]);   // 参数以数组传递

2. bind 方法

const boundFunc = introduce.bind(user);
boundFunc("Java"); // "Charlie codes in Java"

优先级规则
显式绑定 > 隐式绑定(对象方法) > 默认绑定


六、箭头函数的 this

箭头函数没有自身的 this,继承外层词法作用域的 this

const obj = {value: 42,getValue: () => {console.log(this.value); // 指向全局对象}
};
obj.getValue(); // undefined (浏览器中 window.value 未定义)

适用场景

function Timer() {this.seconds = 0;setInterval(() => {this.seconds++; // 正确指向 Timer 实例}, 1000);
}

底层机制
箭头函数的 [[ThisMode]]lexical,不创建自身的 this 绑定。


七、事件处理器中的 this

DOM 事件处理函数中,this 指向触发事件的元素:

<button onclick="console.log(this)">Click</button> 
<!-- 输出 <button> 元素 -->

例外情况(箭头函数)

button.addEventListener("click", () => {console.log(this); // 指向外层 this(通常为 window)
});

八、严格模式的影响总结

场景非严格模式严格模式
独立函数调用全局对象undefined
未绑定方法的调用全局对象undefined
构造函数未使用 new意外修改全局对象抛出错误

九、底层原理深度解析

1. 执行上下文与 this 绑定

每次函数调用时,会创建执行上下文(ExecutionContext),其中包含:

  • LexicalEnvironment:用于变量/函数声明
  • VariableEnvironment:用于 var 变量
  • ThisBinding:确定当前 this

2. [[ThisMode]] 内部属性

函数对象拥有内部属性 [[ThisMode]]

  • lexical:箭头函数,继承外层 this
  • strict:严格模式函数,this 不转为对象
  • global:非严格模式函数,this 可能为全局对象

3. 绑定优先级

  1. new 绑定:new Foo()
  2. 显式绑定:call/apply/bind
  3. 隐式绑定:obj.method()
  4. 默认绑定:独立函数调用

十、特殊场景与陷阱

1. 回调函数中的 this

const loader = {load: function() {fetchData(function() {console.log(this); // 指向全局或 undefined});}
};
// 解决方案:使用箭头函数或 bind

2. 原型链上的 this

function Animal(name) {this.name = name;
}
Animal.prototype.speak = function() {console.log(this.name);
};
const cat = new Animal("Whiskers");
cat.speak(); // "Whiskers"

3. 类(Class)中的 this

类方法默认启用严格模式:

class User {constructor(name) {this.name = name;}sayHi() {console.log(this.name);}
}
const user = new User("Dave");
const say = user.sayHi;
say(); // TypeError: Cannot read property 'name' of undefined

总结与最佳实践

  1. 优先使用箭头函数:避免意外 this 指向问题
  2. 必要时显式绑定:在复杂场景使用 bind
  3. 构造函数始终使用 new:防止全局污染
  4. 事件处理注意上下文:传统函数 vs 箭头函数选择
  5. 严格模式统一行为:推荐启用严格模式

通过理解这些规则和底层机制,开发者可以精准控制 this 的指向,写出更健壮的 JavaScript 代码。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyTorch系列教程:Tensor.view() 方法详解

这篇简明扼要的文章是关于PyTorch中的tensor.view()方法的介绍与应用&#xff0c;与reshape()方法的区别&#xff0c;同时给出示例进行详细解释。 Tensor基础 Tensor(张量)的视图是一个新的Tensor&#xff0c;它与原始Tensor共享相同的底层数据&#xff0c;但具有不同的形状或…

Python数据分析之数据可视化

Python 数据分析重点知识点 本系列不同其他的知识点讲解&#xff0c;力求通过例子让新同学学习用法&#xff0c;帮助老同学快速回忆知识点 可视化系列&#xff1a; Python基础数据分析工具数据处理与分析数据可视化机器学习基础 四、数据可视化 图表类型与选择 根据数据特…

swift -(5) 汇编分析结构体、类的内存布局

一、结构体 在 Swift 标准库中&#xff0c;绝大多数的公开类型都是结构体&#xff0c;而枚举和类只占很小一部分 比如Bool、 Int、 Double、 String、 Array、 Dictionary等常见类型都是结构体 ① struct Date { ② var year: Int ③ var month: Int ④ …

推荐一个比较好的开源的工作流引擎

由于DeepSeek等AI大模型的出现&#xff0c;工作流模式再次流行起来&#xff0c;低代码甚至零代码就可以实现应用开发&#xff0c;而且有DeepSeek这样的超级AI作为大脑&#xff0c;人人都可以开发自动化工作流。 比如搭建邮件助手工作流&#xff0c;可以自动润色各种邮件内容。…

CarPlanner:用于自动驾驶大规模强化学习的一致性自回归轨迹规划

25年2月来自浙大和菜鸟网络的论文“CarPlanner: Consistent Auto-regressive Trajectory Planning for Large-scale Reinforcement Learning in Autonomous Driving”。 轨迹规划对于自动驾驶至关重要&#xff0c;可确保在复杂环境中安全高效地导航。虽然最近基于学习的方法&a…

Fedora41安装MySQL8.4.4

Fedora41安装MySQL8.4.4 Fedora41用yum仓库安装MySQL8.4.4 笔记250310下载安装启动mysqld服务查看生成的初始密码 , 用初始密码登录登录后,必须修改初始密码才能执行其它操作可选设置降低密码强度要求, 使用简单密码降低 validate_password 组件对密码强度的要求 用SET GLOBAL命…

信息安全意识之安全组织架构图

一、信息安全技术概论1.网络在当今社会中的重要作用2.信息安全的内涵 网络出现前&#xff1a;主要面向数据的安全&#xff0c;对信息的机密性、完整性和可用性的保护&#xff0c;即CIA三元组 网络出现后&#xff0c;还涵盖了面向用户的安全&#xff0c;即鉴别&#xff0c;授权&…

安卓Android与iOS设备管理对比:企业选择指南

目录 一、管理方式差异 Android Enterprise方案包含三种典型模式&#xff1a; Apple MDM方案主要提供两种模式&#xff1a; 二、安全防护能力 Android系统特点&#xff1a; 三、应用管理方案 四、设备选择建议 五、典型场景推荐 需求场景 推荐方案 六、决策建议要点…

linunx ubuntu24.04.02装libfuse2导致无法开机进不了桌面解决办法

osu.appimage运行需要libfuse2 然后我就下了fuse,打了两把第二天无法开机 这样是不能开机的 这样是可以开机的 解决办法一&#xff1a;玩星火商店的osu&#xff0c;好了问题解决 解决办法二&#xff1a; 在这个页面 ctrl alt f2进入tty6 sudo apt install ubuntu-desktop 进…

mysql-8.0.41-winx64 手动安装详细教程(2025版)

mysql-8.0.41-winx64 手动安装详细教程&#xff08;2025版&#xff09; 一、下载安装包二、配置环境变量三、安装配置四、启动 MySQL 服务&#xff0c;修改密码 一、下载安装包 安装地址如下&#xff1a; https://dev.mysql.com/downloads/mysql/使用7-zip或其他解压软件&…

wireguard搭配udp2raw部署内网

前言 上一篇写了使用 wireguard 可以非常轻松的进行组网部署&#xff0c;但是如果服务器厂商屏蔽了 udp 端口&#xff0c;那就没法了 针对 udp 被服务器厂商屏蔽的情况&#xff0c;需要使用一款 udp2raw 或 socat 类似的工具&#xff0c;来将 udp 打包成 tcp 进行通信 这里以…

[杂学笔记] TCP和UDP的区别,对http接口解释 , Cookie和Session的区别 ,http和https的区别 , 智能指针 ,断点续传

文章目录 1. TCP和UDP的区别2. 对http接口解释3. Cookie和Session的区别4. http和https的区别5. 智能指针6.断点续传 1. TCP和UDP的区别 tcp的特点&#xff1a; 面向连接&#xff0c;可靠性高&#xff0c;全双工&#xff0c;面向字节流udp特点&#xff1a;无连接&#xff0c;不…

Qt入门笔记

目录 一、前言 二、创建Qt项目 2.1、使用向导创建 2.2、最简单的Qt应用程序 2.2.1、main函数 2.2.2、widget.h文件 2.2.3、widget.cpp文件 2.3、Qt按键Botton 2.3.1、创建一个Botton 2.3.2、信号与槽 2.3.3、按键使用信号与槽的方法 2.4、文件Read与Write-QFile类 2…

Unity辅助工具_头部与svn

Unity调用者按钮增加PlaySideButton using QQu; using UnityEditor; using UnityEngine; [InitializeOnLoad] public class PlaySideButton {static PlaySideButton(){UnityEditorToolbar.RightToolbarGUI.Add(OnRightToolbarGUI);UnityEditorToolbar.LeftToolbarGUI.Add(OnLe…

ubuntu软件

视频软件&#xff0c;大部分的编码都能适应 sudo apt install vlc图片软件 sudo apt install gwenview截图软件 sudo apt install flameshot设置快捷键 flameshot flameshot gui -p /home/cyun/Pictures/flameshot也就是把它保存到一个自定义的路径 菜单更换 sudo apt r…

Spring (十)事务

目录 一 Spring数据库的相关配置&#xff1a; 1 导入包&#xff1a; 2 配置数据库连接信息 3 可以直接使用&#xff1a;DataSource,JdbcTemplate 二 事务管理&#xff1a; 1 事务管理的实现 1.1 开启Spring事务管理 1.2 为指定方法添加事务 2 关键类与接口 2.1 事务拦…

【MySQL_04】数据库基本操作(用户管理--配置文件--远程连接--数据库信息查看、创建、删除)

文章目录 一、MySQL 用户管理1.1 用户管理1.11 mysql.user表详解1.12 添加用户1.13 修改用户权限1.14 删除用户1.15 密码问题 二、MySQL 配置文件2.1 配置文件位置2.2 配置文件结构2.3 常用配置参数 三、MySQL远程连接四、数据库的查看、创建、删除4.1 查看数据库4.2 创建、删除…

Java算术运算符与算术表达式

Java算术运算符包括&#xff08;加、正号&#xff09;、-&#xff08;减、负号&#xff09;、*&#xff08;乘&#xff09;、/&#xff08;除&#xff09;、%&#xff08;求余&#xff09;、&#xff08;自增&#xff09;和--&#xff08;自减&#xff09;。它们用于构建算术表…

【网络】HTTP协议、HTTPS协议

HTTP与HTTPS HTTP协议概述 HTTP(超文本传输协议):工作在OSI顶层应用层,用于客户端(浏览器)与服务器之间的通信,B/S模式 无状态:每次请求独立,服务器不保存客户端状态(通过Cookie/Session扩展状态管理)。基于TCP:默认端口80(HTTP)、443(HTTPS),保证可靠传输。请…

Linux 网络:skb 数据管理

文章目录 1. 前言2. skb 数据管理2.1 初始化2.2 数据的插入2.2.1 在头部插入数据2.2.2 在尾部插入数据 2.2 数据的移除 3. 小结 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. skb 数据管理 数…