JS的this关键字怎么用

javascript 中的 this 指向由函数调用方式决定,而非定义位置。1. 默认绑定:普通函数调用时,this 指向全局对象(浏览器中为 window),严格模式下为 undefined;2. 隐式绑定:作为对象方法调用时,this 指向调用该方法的对象,但方法被提取后单独调用会丢失绑定,退回到默认绑定;3. 显式绑定:通过 call、apply 或 bind 方法可显式指定 this 指向;4. new 绑定:使用 new 调用构造函数时,this 指向新创建的实例对象;5. 箭头函数的词法绑定:箭头函数没有自己的 this,其 this 由外层作用域决定,调用方式不影响其指向,从而简化了 this 的管理,尤其在回调函数中避免了上下文丢失问题。理解 this 的核心在于分析函数调用时的执行上下文,掌握这五种绑定规则是解决 this 相关问题的关键,最终 this 的值在运行时根据调用位置动态确定,这一机制体现了 javascript 的灵活性与动态性。

JS的this关键字怎么用

JavaScript 中的

this

关键字,它指向的不是函数定义的位置,而是函数被调用时的“执行上下文”。简单来说,

this

的值在运行时动态确定,完全取决于函数是如何被调用的。理解它,是掌握 JS 核心的关键一步。

要真正掌握

this

,我们需要深入理解它在不同调用模式下的绑定规则。这就像是

this

有一套自己的“行为准则”。

默认绑定 (Default Binding): 当函数作为普通函数独立调用时,

this

通常指向全局对象(在浏览器中是

window

,在 Node.js 中是

global

)。但如果处于严格模式 (

'use strict'

) 下,

this

会是

undefined

。这是最容易让人困惑的地方,因为你可能觉得它应该指向某个特定的东西,结果却指向了全局。

function showThis() {  console.log(this);}showThis(); // 在浏览器中输出 Window 对象,在严格模式下输出 undefined'use strict';function strictShowThis() {  console.log(this);}strictShowThis(); // 输出 undefined

隐式绑定 (Implicit Binding): 当函数作为对象的一个方法被调用时,

this

会指向调用该方法的对象。这是我们最常用也最符合直觉的场景。

const person = {  name: '张三',  greet: function() {    console.log(`你好,我是 ${this.name}`);  }};person.greet(); // 输出:你好,我是 张三 (this 指向 person 对象)

但要注意,如果这个方法被“提取”出来单独调用,隐式绑定就会失效,转而使用默认绑定。

const anotherGreet = person.greet;anotherGreet(); // 输出:你好,我是 undefined (或在浏览器中是 "你好,我是 Window")

显式绑定 (Explicit Binding): 通过

call()

,

apply()

, 或

bind()

方法,你可以强制指定

this

的值。这给了我们极大的灵活性去控制函数的执行上下文。

function introduce(age, city) {  console.log(`我是 ${this.name},${age} 岁,来自 ${city}`);}const person2 = { name: '李四' };introduce.call(person2, 30, '北京'); // 输出:我是 李四,30 岁,来自 北京introduce.apply(person2, [25, '上海']); // 输出:我是 李四,25 岁,来自 上海const boundIntroduce = introduce.bind(person2, 40);boundIntroduce('广州'); // 输出:我是 李四,40 岁,来自 广州

new 绑定 (New Binding): 当使用

new

关键字调用一个构造函数时,会创建一个新的对象,并将这个新对象绑定到构造函数中的

this

function Car(make, model) {  this.make = make;  this.model = model;  console.log(this); // 这里的 this 就是新创建的 Car 实例}const myCar = new Car('Honda', 'CRV'); // 输出 Car { make: 'Honda', model: 'CRV' }

箭头函数 (Arrow Functions) 的词法绑定: 箭头函数没有自己的

this

绑定。它的

this

值是在其定义时,由外层(词法)作用域的

this

决定的。它不会受函数调用方式的影响。这让它在处理回调函数时特别方便。

const user = {  name: '王五',  logName: function() {    // 这里的 this 指向 user 对象    setTimeout(function() {      console.log(this.name); // 这里的 this 指向全局对象 (或 undefined)    }, 100);  },  logNameArrow: function() {    // 这里的 this 指向 user 对象    setTimeout(() => {      console.log(this.name); // 这里的 this 依然指向 user 对象    }, 100);  }};user.logName(); // 输出 undefined (或 Window)user.logNameArrow(); // 输出 王五

为什么JavaScript的this行为如此多变且难以捉摸?

在我看来,

this

行为多变的核心原因在于 JavaScript 的设计哲学:它是一种非常灵活的语言,函数是“一等公民”,可以被当作值传递,也可以作为对象的方法调用。这种灵活性导致了

this

的值必须在运行时根据“函数是如何被调用”来动态决定,而不是像一些静态语言那样在编译时就确定。这无疑增加了学习曲线,但一旦理解了其背后的绑定规则,你就会发现这种动态性其实非常强大。

我们常常会遇到这样的情况:一个函数在某个上下文中工作得好好的,但当它作为回调函数被传递出去后,

this

突然就“跑偏”了。这正是因为调用上下文变了。比如,在事件监听器中,回调函数里的

this

默认会指向触发事件的 DOM 元素,而不是你期望的某个组件实例。这种切换,正是

this

动态绑定的体现。

理解这些规则,尤其是“调用位置决定

this

”这个核心思想,是解开

this

谜团的钥匙。当你调试

this

问题时,第一步永远是去观察函数被调用的那一刻,它前面有没有点 (

.

),有没有

new

,有没有

call

/

apply

/

bind

,或者它是不是一个箭头函数。这就像是侦探破案,找到“案发现场”才能找到真相。

箭头函数如何简化this的管理?

箭头函数是 ES6 引入的一个非常棒的特性,它在

this

的处理上与传统函数有着本质的区别。正如前面提到的,箭头函数没有自己的

this

绑定,它会捕获其定义时所处的“词法作用域”的

this

值。这意味着,无论箭头函数如何被调用,它的

this

都会保持不变,始终指向其外层非箭头函数的

this

这在处理回调函数,尤其是异步操作的回调时,简直是“救星”。在 ES6 之前,我们为了在

setTimeout

或事件处理函数中保持

this

的指向,不得不使用

var self = this;

这样的模式,或者使用

bind

方法。比如:

// ES5 时代常见的 this 陷阱与解决方案function Timer() {  this.seconds = 0;  // var self = this; // 方案一:保存 this  setInterval(function() {    // console.log(self.seconds++); // 使用保存的 self    // 或者    // console.log(this.seconds++); // 这里的 this 指向 window/undefined  }.bind(this), 

以上就是JS的this关键字怎么用的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1516448.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月20日 10:03:47
下一篇 2025年12月16日 11:36:34

相关推荐

  • JS如何实现扫码功能

    javascript实现扫码功能的核心是通过getusermedia api获取摄像头视频流,并结合jsqr、quaggajs或zxing-js等解码库对视频帧进行实时图像识别与解码,整个过程需在https环境下运行以确保权限正常调用;首先利用navigator.mediadevices.getus…

    好文分享 2025年12月20日
    000
  • js怎么判断对象是否有某属性

    判断javascript对象是否拥有某个属性,需明确是检查自身属性还是包括原型链。1. 使用 ‘propertyname’ in object 检查对象自身及原型链上的属性,只要存在即返回true;2. 使用 object.hasownproperty(‘prop…

    2025年12月20日
    000
  • JS如何处理JSON数据

    JavaScript处理JSON的核心是JSON.parse()和JSON.stringify()。前者将JSON字符串转为JS对象,需用try…catch捕获非法格式错误;后者将JS对象序列化为JSON字符串,支持replacer和space参数优化输出。解析时需注意JSON语法严格性…

    2025年12月20日
    000
  • 什么是生成器?生成器的惰性求值

    生成器与传统数据结构的根本差异在于其惰性求值和按需生成的机制,1. 列表等传统结构会一次性将所有数据加载到内存,而生成器通过yield关键字实现函数执行的暂停与恢复,仅在需要时生成值;2. 这使得生成器内存占用极低,适合处理海量数据或无限序列;3. 生成器是一次性的,无法重复遍历,这是为内存效率做出…

    2025年12月20日
    000
  • 什么是职责链模式?职责链的实现

    职责链模式通过将请求沿链传递实现发送者与接收者的解耦,如审批流程中部门经理、总监、总经理依次处理请求,各处理者决定是否处理或转发,从而实现灵活扩展,但需注意链过长影响性能,可通过优化结构、缓存或拆分链来解决,其与中间件模式的主要区别在于控制权和灵活性不同。 职责链模式,简单来说,就是让多个对象都有机…

    2025年12月20日
    000
  • JS如何实现进度条

    js实现进度条的核心是动态更新视觉呈现并与异步操作进度关联,需结合html结构、css样式和javascript逻辑实现;1. 创建包含外层容器和内层进度条的html结构;2. 使用css设置进度条样式并支持宽度动态变化;3. 编写javascript函数updateprogressbar通过修改s…

    2025年12月20日
    000
  • 什么是WebGL?WebGL的基本概念

    webgl是一种基于javascript的图形api,它允许在浏览器中无需插件即可通过gpu渲染高性能2d和3d图形,其核心是将opengl es 2.0的渲染管线移植到web端,使开发者能直接操作顶点、着色器、缓冲区和纹理等底层资源,实现对图形硬件的精细控制;与canvas 2d这种基于cpu的像…

    2025年12月20日
    000
  • js 如何读取cookie的值

    读取javascript中cookie的值需通过解析document.cookie字符串实现,因为其返回的是类似”key1=value1; key2=value2″的格式,而非对象。1. 使用document.cookie获取所有cookie字符串;2. 通过分号分割成数组;…

    2025年12月20日
    000
  • JavaScript:解决HTML元素加载前脚本执行导致Null值问题

    本文旨在解决JavaScript脚本在HTML元素加载之前执行,导致document.getElementById()等方法返回null值的问题。文章将介绍两种常用的解决方案:使用defer属性延迟外部脚本的执行,以及使用type=”module”将内联脚本声明为模块,确保脚…

    2025年12月20日
    000
  • 构建按工作日和工作时间运行的JavaScript计数器

    本文详细介绍了如何使用JavaScript构建一个精确的定时计数器。该计数器每分钟递增一次,但仅在预设的工作日(周一至周五)和工作时间(如上午6点至晚上8点)内运行。它能在非工作时间暂停递增但显示当前值,并在每月的第一天自动重置,确保计数逻辑的准确性和灵活性。 概述 在许多应用场景中,我们需要一个计…

    2025年12月20日
    000
  • JS中的树是什么?二叉树的基本概念

    二叉树是JavaScript中重要的分层数据结构,每个节点最多有两个子节点,广泛用于高效搜索、排序和数据组织;通过节点值比较实现插入与查找,常用遍历方式包括前序、中序和后序,其中中序遍历可得到有序数据;为避免树形退化为链表,需使用AVL或红黑树等平衡二叉树以维持O(log n)操作效率;删除节点时需…

    2025年12月20日
    000
  • js 如何用isEmpty检查数组是否为空

    最直接可靠的方法是检查数组的 length 属性是否为 0,1. 使用 arr.length === 0 判断数组是否为空,这是 o(1) 操作且准确高效;2. 避免使用 if (arr) 判断,因为空数组是真值(truthy),条件会成立导致误判;3. 在判断前应先用 array.isarray(…

    2025年12月20日
    000
  • js如何实现base64编码

    处理ascii字符串直接用btoa();2. 处理unicode字符串需先用textencoder转为uint8array,再转换为二进制字符串后使用btoa();3. 处理二进制数据如文件或图片应使用filereader的readasdataurl()方法获取base64编码。btoa()不能直接…

    2025年12月20日
    000
  • 什么是代数数据类型?ADT的概念

    ADT的核心组成部分包括:1. 和类型(Sum Types),表示一个值可以是多种类型之一,如Success或Failure;2. 积类型(Product Types),表示一个类型由多个字段组合而成,如包含name和age的Person类型;3. 构造器(Constructors),用于创建ADT…

    2025年12月20日
    000
  • 使用 CSS 实现水平滚动文本的淡出效果

    本文介绍了如何使用 CSS 实现文本在水平滚动时产生淡出效果。通过巧妙地运用线性渐变和 background-clip 属性,我们可以创建一个视觉上吸引人的滚动文本效果,尤其适用于背景不均匀的场景。文章提供了详细的代码示例,并解释了关键 CSS 属性的用法,帮助读者轻松掌握该技巧。 实现水平滚动文本…

    2025年12月20日
    000
  • 优化React Hook:基于滚动速度控制导航栏可见性

    本文将优化一个React Hook,该Hook用于根据滚动位置、滚动方向和滚动速度来控制导航栏的可见性。通过使用useCallback来避免不必要的函数重新创建,并精简useEffect的依赖项,提升Hook的性能和稳定性,实现更流畅的导航栏显示/隐藏效果。 优化React Hook以控制导航栏可见…

    2025年12月20日
    000
  • 实现水平滚动文本的渐隐效果

    本文将介绍如何使用 CSS 实现水平滚动文本的渐隐效果,使其在滚动到边缘时逐渐消失。这种效果尤其适用于需要在非均匀背景上展示长文本,同时又希望避免文本超出容器边界的情况。我们将通过结合线性渐变和 background-clip 属性,创建一个优雅且实用的文本展示方案。 实现原理 实现文本渐隐效果的核…

    2025年12月20日 好文分享
    000
  • 使用 JavaScript 在电话号码输入框中每两位数字间添加空格

    本文将介绍如何使用 JavaScript 为电话号码输入框实现每两位数字之间自动添加空格的功能。由于 不允许直接插入空格,我们将使用 并结合 JavaScript 的事件监听和字符串处理方法,实现输入时自动格式化电话号码的效果。 实现原理 核心思路是监听 元素的 input 事件,在每次输入时,先移…

    2025年12月20日
    000
  • JS如何实现数据绑定

    答案:JS数据绑定通过监听数据变化自动更新视图,核心方法包括手动更新、Object.defineProperty()、Proxy、发布/订阅模式及MVVM框架。1. 手动更新需每次调用函数修改DOM,效率低;2. Object.defineProperty()可监听属性读写,但无法监控新增或删除属性…

    2025年12月20日
    000
  • js 如何添加右键菜单

    在javascript中添加右键菜单需先阻止默认事件并创建自定义菜单。1. 使用contextmenu事件监听并调用event.preventdefault()阻止默认菜单;2. 用html和css构建菜单结构并隐藏;3. 通过event.clientx和event.clienty获取坐标,设置菜单…

    2025年12月20日
    000

发表回复

登录后才能评论
关注微信