js疑惑

news/2025/10/4 17:03:11/文章来源:https://www.cnblogs.com/BKYNEKO/p/19125741

textBox.addEventListener("keydown", function (event) {
  console.log(`You pressed "${event.key}".`);
});这个函数接收的"keydown",到底是什么意思我还是没看懂为什么会这样写看着也不像是接收参数的形参,而且有些函数还写了(null,其他参数)

 

您提的问题非常好,直击了JavaScript中一个非常核心且初学者容易困惑的概念:事件监听回调函数

我们用一个简单的比喻来理解,然后再深入技术细节。

 

简单的比喻:订阅杂志

 

想象一下,textBox 是一个“邮局”,addEventListener 就是你去邮局办理的“订阅服务”。

你去柜台办理订阅时,需要告诉工作人员两件事:

  1. 你要订阅什么杂志? (比如《电脑爱好者》)

  2. 杂志到了寄给谁? (你的家庭地址)

在您的代码 textBox.addEventListener("keydown", function (event) { ... }); 中:

  • "keydown" 就相当于杂志的名字 《按键按下》。它不是一个变量(形参),而是一个具体的、预定义好的事件名称。你是在明确告诉浏览器:“我只对‘键盘按键被按下’这个事件感兴趣。”

  • function (event) { ... } 就相当于你的家庭地址和收件人。你是在告诉浏览器:“一旦《按键按下》这本杂志到了(也就是事件发生了),就把这封信(event对象)送到这个函数(你的家)来处理。”

所以,addEventListener 函数本身接收了两个主要的参数:

  1. 第一个参数 (事件类型): 是一个字符串,用来指定要监听的事件名称。浏览器内置了很多这样的事件名称,比如 "click"(点击事件)、"mouseover"(鼠标悬停事件)、"keyup"(按键抬起事件)等等。

  2. 第二个参数 (监听器/回调函数): 是一个函数,用来定义事件发生后应该做什么。这个函数不会立即执行,而是“注册”给浏览器,等待事件发生时由浏览器来调用。


 

深入解析 addEventListener

 

它的标准语法是: element.addEventListener(type, listener);

  • type (类型): 就是我们说的事件名称字符串,例如 "keydown"。它告诉 addEventListener 要监听哪一种用户交互或浏览器行为。

  • listener (监听器): 就是那个函数 function(event){...}。它在编程中通常被称为 “回调函数 (Callback Function)”。所谓“回调”,意思就是你把这个函数交给了浏览器,浏览器并不会立即调用它,而是在将来某个特定的时间点(比如按键被按下时)回过头来调用你定义的这个函数。

当浏览器调用你的回调函数时,它会自动创建一个包含事件所有详细信息的对象,并把它作为第一个参数传递给你的函数。我们通常把它命名为 event (或者 e),这样在函数内部,我们就可以通过 event.key 来获取具体按下了哪个键。


 

关于您提到的 “null”

 

您提到的“有些函数还写了个null,然后再写要接收的参数”,这通常与JavaScript中的 this 上下文以及 callapply 方法有关,与 addEventListener 的工作方式不同。

这是一个非常好的观察!您很可能看到的是类似这样的代码:

JavaScript
 
someFunction.call(null, param1, param2);

我们来简单解释一下:

在JavaScript中,函数不仅可以被直接调用 someFunction(),还可以通过 .call().apply() 方法来调用。这些方法的作用是手动指定函数在执行时的 this 关键字应该指向谁

.call() 的第一个参数就是用来设置 this 的值。

  • 为什么要传 null?

    当一个函数内部并不依赖 this 上下文,或者我们希望它在全局作用域下执行时,我们就可以在第一个参数的位置传入 null 或 undefined。这相当于在说:“嘿,call 方法,我知道你需要一个this的值,但我这个函数用不到它,所以给你一个null占位,你直接帮我把后面的参数传进去执行就行了。”

举个例子:

JavaScript
 
function add(a, b) {// 这个函数内部完全没有用到 thisreturn a + b;
}// 我们想用 .call 的方式来调用它
let result = add.call(null, 5, 10); // 第一个参数是 null,因为 add 函数不关心 this 是谁console.log(result); // 输出 15

 

总结

 

  1. "keydown" 不是形参,而是一个事件类型的名称(字符串),用来告诉 addEventListener 你想监听哪一种事件。

  2. function(event){...} 是一个回调函数,你把它交给浏览器,当事件发生时,浏览器会自动调用它,并把包含事件详情的 event 对象传给它。

  3. 您看到的 null 用法,通常是在使用 .call().apply() 调用函数时,作为 this 上下文的一个占位符,表示“我不需要为这次调用指定一个特殊的this对象”。

 

 

这个null的解释符合你刚刚的解释吗。              ...(record.status === 0 || record.status === 1
                ? [
                    {
                      label: record.status === 0 ? '取消发布' : '发布',
                      onClick: handleEditStatus.bind(null, record)
                    }
                  ]
                : [])
            ]"

 

是的,完全符合!您举的这个例子非常好,它完美地展示了我刚才解释的 this 上下文概念,并且引出了一个与 .call() 相似但又很关键的不同点,那就是 .bind() 的作用。

您看到的 handleEditStatus.bind(null, record) 这一行代码里,null 的意义和我之前解释的完全一样:它是在告诉JavaScript引擎:“我不需要为 handleEditStatus 这个函数绑定一个特殊的 this 上下文,使用默认的就行。”


 

这里 bind 的特殊作用

 

现在,我们来深入理解一下为什么这里用的是 .bind(),而不是 .call()。这能让您对JavaScript的理解更上一层楼。

.call().bind() 都能设置 this 上下文,但它们有一个核心区别:

  • .call(this, arg1, arg2): 立即执行这个函数。就像直接打电话并说话。

  • .bind(this, arg1, arg2): 不执行函数,而是创建一个新的、已经预设好 this 和参数的函数。就像在手机里存一个“快捷拨号”,你存的时候电话并不会打出去,只有等你按下那个快捷键时才会拨号。

在您的例子中,onClick 需要的是一个可以被随时调用的“快捷拨号”(一个函数),而不是函数立即执行的结果。

  • 如果写成 handleEditStatus.call(null, record):那么在页面渲染的时候,这行代码会立刻执行 handleEditStatus 函数,而不是等到用户点击按钮时才执行。这显然是错误的。

  • 而写成 handleEditStatus.bind(null, record):这行代码不会执行 handleEditStatus。它会创建一个全新的、匿名的函数。这个新函数的特点是:

    1. 它的 this 值被永久地绑定为了 null(即默认值)。

    2. 它的第一个参数被永久地预设为了 record 这个变量。


 

完整流程分解

 

让我们把您的代码场景完整地走一遍:

  1. 页面渲染时

    • 代码执行到 onClick: handleEditStatus.bind(null, record)

    • JavaScript创建了一个新的函数(我们称之为 boundFunction)。这个 boundFunction 内部已经“记住”了它的thisnull,并且它将来被调用时,第一个参数必须是 record

    • 然后,这个 boundFunction 被赋值给了 onClick 属性,作为点击事件的处理程序。

  2. 用户点击按钮时

    • 浏览器触发了点击事件,于是调用了之前存好的 boundFunction

    • boundFunction 被调用后,实际上就等于执行了 handleEditStatus(record)

总结一下:

您看到的 null 和我解释的 call(null, ...) 中的 null 意义完全相同,都是用来忽略 this 上下文的。

而这里之所以使用 .bind 而不是 .call,是因为事件处理(如 onClick)需要的是一个函数定义作为“待办事项”,而不是一个函数立即执行的结果。.bind 恰好能创建一个“预备好的”新函数,完美地满足了这个需求。

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

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

相关文章

使用 Git Submodule 管理微服务项目:从繁琐到高效 - 指南

使用 Git Submodule 管理微服务项目:从繁琐到高效 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consola…

如何识别网页用什么网站做的女装关键词排名

一个网站,其实说白了就是某几个特定功能的组合,而更换用户头像就在这些功能之中。今天就来做个测试,针对不同的用户,实现头像上传功能。先给大家展示下成品效果图:思路针对不同的用户上传头像,我们要为每一…

邯郸专业做网站多少钱做印刷网站公司哪家好

一、接口自动化测试中,会用到测试账号,如何合理运用账号? 账号一般用于接口登录、接口用例传参、操作sql等,目前账号是写到yaml配置文件里,如果1个账户使用会出现资源冲突,可以配置多个账号使用&#xff0…

佛山专业建设网站平台兼职python做网站

STM32定时器定时及其应用 定时器概述☆定时器相关配置CubeMX工程配置及程序实现固件库程序设计及实现 定时器概述 1. 工作原理 使用精准的时基,通过硬件的方式,实现定时功能。定时器核心就是计数器 2. 定时器分类   基本定时器(TIM6~TIM7…

深入解析:单元测试学习+AI辅助单测

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

20251004国庆模拟4

对于 20251004 CSP-S 模拟的总结Part 1 题目 点击快速下载 有两道是洛谷的: T2: P5979 [PA2014] Druzyny T3: P2371 [国家集训队] 墨墨的等式 ⚠警告: P5979 和本场的 T3 并不完全一样。 Part 2 考试重要时间线 8:00…

珂朵莉树 ODT

能干什么/局限性 高效处理区间平推(区间赋值)的问题。 在随机数据下飞快。 如果没有区间平推,或者区间平推的操作数量可以被卡得很少甚至没有,就不适用。 前置知识set没了。 建点 每个点要维护一个区间,以及这个区…

2025多校CSP模拟赛2

2025多校CSP模拟赛2 狂写大树套树通过 \(T3\) 的救赎感。 T1 查询 第一眼感觉不好做。 首先直接找绝对没前途,考虑二分 \(v\)。 问题变成了统计 \(a_j+b_j\times c_i\le v\) 的数量,变换一下变成: \[c_i\le \frac{v…

网站查询访问界面设计模式读后感

如今人们对于住宅需求早已今非昔比,不但需要足够大的空间,而且对于住宅所处位置是否交通便利,环境如何,光照情况都有要求,但是最关注的问题还是住宅的安全问题。如今的社会科技发达,不法分子的手段也层出不…

io多路复用:reactor模型的封装及与上层简单业务的搭建(webserver)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

详细介绍:深入了解linux网络—— 基于UDP实现翻译和聊天功能

详细介绍:深入了解linux网络—— 基于UDP实现翻译和聊天功能pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Cons…

详细介绍:vLLM - GPUModelRunner

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Rewind: Codeforces Round 1055 (Div.1+Div.2)

E. Monotone Subsequence \(\text{time limit: 2000 ms}\\\text{memory limit: 1024 MB}\) 这是一道交互题 题意: 由 \(\text{Thm. Erdős–Szekeres}\) ,我们知道对任意长为 \(n^2+1\) 的排列必有一个长为 \(n+1\) …

10.4模拟赛总结

2025-2026 赛季 OIFHA 第三十四场 NOIP 模拟赛总结 一休尼(forever) 原题:CF5E Bindian Signalizing 长度为 \(n\) 的整数序列 \(a\) 。求整数对 \((i,j)\),\(i,j\in [1,n]\) 的个数,满足 \((i,j)\) 之间存在至少…

做网站动图的软件游戏开发软件有哪些

一、简介 java8新添加了一个特性:流Stream。Stream让开发者能够以一种声明的方式处理数据源(集合、数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation)和大批量数据操作 (bulk data op…

重庆网站设计建设备案网站服务内容

探索AI图像安全,助力可信AI发展 0. 前言1. 人工智能发展与安全挑战1.1 人工智能及其发展1.2 人工智能安全挑战 2. WAIC 2023 多模态基础大模型的可信 AI2.1 WAIC 2023 专题论坛2.2 走进合合信息 3. AI 图像安全3.1 图像篡改检测3.2 生成式图像鉴别3.3 OCR 对抗攻击技…

01.linux基础

01.linux基础 1.你平时在公司主要做什么?2.你们原来公司的网站架构是怎么样的?3.你对哪一块比较熟练或者精通?4.介绍一下负载均衡?5.lvs 内部原理?6.nginx lvs haproxy 三个有什么区别?7.lvs 主要3种工作模式原…

详细介绍:Kubernetes实战:MariaDB误删恢复与数据持久化

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

我的世界封面制作网站企业网站软件

一:prototype大概概念和用途“prototype”字面翻译是“原型”,是javascript实现继承的主要手段。粗略来说就是:prototype是javascript中的函数(function)的一个保留属性,并且它的值是一个对象(我们可以称这个对象为&qu…