在事件处理函数中的 this

简介: 本文内容主要是,针对事件处理函数中如何使用 this 的几种方法及区别。

前言


本文内容主要是,针对事件处理函数中如何使用 this 的几种方法及区别。


正文


一、Owner


我们将在本文讨论的问题是:在函数 doSomething()this 指向的是什么?

注意,本文通篇均在非严格模式下进行。


<script>
  function doSomething() {
    this.style.color = '#c00'
  }
</script>


在 JavaScript 中, this 总是指我们正在执行的函数的“owner”,或者更确切地说,是指函数作为其方法的对象。当我们在页面中定义我们函数 doSomething() 时,它的“owner”是页面,或者更确切地说,是 JavaScript 的 window 对象(或全局对象)。但是,onclick 属性归它所属的 HTML 元素所有。


这种“ownership”是 JavaScript 面向对象方法的结果。有关更多信息,请参阅作为关联数组的对象页面。

------------ window --------------------------------------
|                                          / \           |
|                                           |            |
|                                          this          |
|   ----------------                        |            |
|   | HTML element | <-- this         -----------------  |
|   ----------------      |           | doSomething() |  |
|               |         |           -----------------  |
|          --------------------                          |
|          | onclick property |                          |
|          --------------------                          |
|                                                        |
----------------------------------------------------------


如果我们在没有任何准备的情况下执行 doSomething(),则 this 关键字指向 window 对象,该函数会尝试更改 window 对象的 style.color。由于 window 没有 style 对象,该函数会失败并产生 JavaScript 错误(TypeError)。


二、Copying


如果我们想充分利用 this,我们必须注意使用它的函数是由正确的 HTML 元素“拥有”的。换句话说,我们必须将函数复制到我们的 onclick 属性。传统的事件注册会处理它。

element.onclick = doSomething


该函数被完整地复制到 onclick 属性(现在变成了一个方法)。因此,如果执行事件处理程序,this 会指向 HTML 元素,并且它的 color 会发生变化。

------------ window --------------------------------------
|                                                        |
|                                                        |
|                                                        |
|   ----------------                                     |
|   | HTML element | <-- this         -----------------  |
|   ----------------      |           | doSomething() |  |
|               |         |           -----------------  |
|          -----------------------          |            |
|          |copy of doSomething()|  <-- copy function    |
|          -----------------------                       |
|                                                        |
----------------------------------------------------------


当然是我们可以将函数复制到多个事件处理程序。每次 this 将指向正确的 HTML 元素:

------------ window --------------------------------------
|                                                        |
|                                                        |
|                                                        |
|   ----------------                                     |
|   | HTML element | <-- this         -----------------  |
|   ----------------      |           | doSomething() |  |
|               |         |           -----------------  |
|          -----------------------          |            |
|          |copy of doSomething()|  <-- copy function    |
|          -----------------------          |            |
|                                           |            |
|   -----------------------                 |            |
|   | another HTML element| <-- this        |            |
|   -----------------------     |           |            |
|               |               |           |            |
|          -----------------------          |            |
|          |copy of doSomething()|  <-- copy function    |
|          -----------------------                       |
|                                                        |
----------------------------------------------------------


因此,你可以最大程度地使用它。每次调用该函数时, this 指的是当前正在处理事件的 HTML 元素,即“拥有” doSomething() 副本的 HTML 元素。


三、Referring


但是,如果你使用内联事件注册

<element onclick="doSomething()">doSomething...</element>


你不要复制功能!相反,你指向它,差异至关重要。onclick 属性不包含实际的函数,而只是一个函数调用:

doSomething()


所以这相当于,前往 doSomething() 并执行它。当我们到达 doSomething() 时,this 关键字再次指向全局 window 对象,并且该函数返回错误消息(TypeError)。

------------ window --------------------------------------
|                                          / \           |
|                                           |            |
|                                          this          |
|   ----------------                        |            |
|   | HTML element | <-- this         -----------------  |
|   ----------------      |           | doSomething() |  |
|               |         |           -----------------  |
|          -----------------------         / \           |
|          | go to doSomething() |          |            |
|          | and execute it      | ---- reference to     |
|          -----------------------       function        |
|                                                        |
----------------------------------------------------------


四、The difference


如果你想使用 this 来访问正在处理事件的 HTML 元素,你必须确保 this 关键字实际上已写入 onclick 属性。只有在这种情况下,this 才指向事件处理程序注册到的 HTML 元素。因此,如果你这样处理:

element.onclick = doSomething
alert(element.onclick)


你将会得到:

function doSomething() {
  this.style.color = '#c00'
}


如你所见,this 关键字存在于 onclick 方法中。因此 this 指向 HTML 元素。

但是,如果你这样处理:

<element onclick="doSomething()">doSomething...</element>
alert(element.onclick)


你得到的是:

function onclick(event) {
  doSomething()
}


这仅仅是对函数 doSomething() 的引用。onclick 方法中不存在 this 关键字,因此 this 不指向 HTML 元素。


五、Examples - copying


以下情况  this 会写入 onclick 方法:

element.onclick = doSomething
element.addEventListener('click', doSomething, false)
element.onclick = function () { this.style.color = '#c00' }
<element onclick="this.style.color = '#c00'">doSomething...</element>


六、Examples - referring


以下情况 this 指向 window 对象:

element.onclick = function () { doSomething() }
element.attachEvent('onclick', doSomething)
<element onclick="doSomething()">doSomething...</element>


请注意 attachEvent() 的存在。 Microsoft 事件注册模型的主要缺点是 attachEvent() 创建对函数的引用而不复制它。因此,有时无法知道当前是哪个 HTML 处理该事件。


七、Combination


使用内联事件注册时,你还可以将 this 发送到该函数,以便你仍然可以使用它:

<element onclick="doSomething(this)">doSomething...</element>
function doSomething(obj) {
  // `this` is present in the event handler and is sent to the function
  // `obj` now refers to the HTML element, so we can do
  obj.style.color = '#c00'
}


八、TODO List



九、References



目录
相关文章
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
663 2
基于Android P,自定义Android开机动画的方法
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
348 5
|
人工智能 前端开发 测试技术
探索前端与 AI 的结合:如何用 GPT-4 助力开发效率
本文介绍了 GPT-4 如何成为前端开发者的“神队友”,让开发变得更加高效愉快。无论是需求到代码的自动生成、快速调试和性能优化,还是自动化测试和技术选型,GPT-4 都能提供极大的帮助。通过智能生成代码、捕捉 BUG、优化性能、自动化测试生成以及技术支持,GPT-4 成为开发者不可或缺的工具,帮助他们从繁重的手动任务中解脱出来,专注于创新和创意。GPT-4 正在彻底改变开发流程,让开发者从“辛苦码农”转变为“效率王者”。
480 0
探索前端与 AI 的结合:如何用 GPT-4 助力开发效率
|
机器学习/深度学习 人工智能 自动驾驶
5G NR:下一代移动通信的基石
5G NR:下一代移动通信的基石
1595 1
|
安全 网络协议 物联网
车联网的IP
车联网中的IP操作并不是一个可以直接用数量来界定的概念,因为它涉及到多个层面和复杂的网络通信过程。然而,可以从车联网的架构和网络通信的角度来探讨车联网中可能涉及的IP相关操作。车联网架构,车联网架构通常包含多层,从物理层、链路层、网络层、传输层到应用层。在每一层中,都可能涉及到IP相关的操作,但具体的操作方式会根据层级的不同而有所差异。
|
机器学习/深度学习 监控 算法
深度学习在图像识别中的创新应用与未来趋势###
【10月更文挑战第14天】 本文探讨了深度学习技术在图像识别领域的创新突破,强调其在提升识别精度、效率及拓展应用场景上的关键作用。通过对比传统方法,凸显了深度学习模型的优越性,并展望其未来发展趋势,包括模型优化、跨模态学习及隐私保护等方向。 ###
383 0
|
边缘计算 安全 物联网
边缘计算在物联网中的作用:技术深度解析
【7月更文挑战第28天】边缘计算在物联网中发挥着至关重要的作用。通过降低延迟、减少网络负载、提高隐私和安全性以及增强离线功能等优势,边缘计算为物联网带来了更加高效、智能和安全的解决方案。未来随着技术的不断进步和应用场景的拓展,边缘计算将在物联网领域发挥更加重要的作用
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的疫情防控自动售货机系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的疫情防控自动售货机系统附带文章源码部署视频讲解等
294 2
|
数据采集 分布式计算 数据挖掘
数据收集与整合
数据收集与整合
395 2
|
网络协议 安全 Linux
TCP 三次握手与四次挥手深入探究(大图解)
TCP 三次握手与四次挥手深入探究(大图解)
985 1

热门文章

最新文章