PPK 谈 JavaScript 的 this 关键字 [翻译]


Posted in Javascript onSeptember 29, 2009

下面先讲如何在event handling(事件处理)中用它,再接着是讲 this 的其他用法。

自己本身

先来看看函数 doSomething() 里的 this 到底是指向(refer to)了什么?

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

JavaScript的 this 总指向所运行的函数“自己本身”。也就是说,它是一种指向函数对象的方法。在页面中定义 doSomething() 函数,自己本身是指页面。也就是说,是指 JavaScript 的 window 对象(全局对象)。而 onclick 属性它自己本身是属 HTML 元素所有。

这个“所有权”是 JavaScript 的 OO(面向对象)特性的后果。在 把对象作关联数组 页面中有更多信息。

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

如果 doSomething() 运行时没有任何与之预留相关的话,关键字 this 指向 window(窗口) ,该函数将会改动 window 的 style.color。而 window 没有 style 这样的对象,所以该函数会引发 JavaScript 的错误。

拷贝(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() 的拷贝)。

指向(referring)

要是用 行内事件注册呢?

<element onclick="doSomething()">

这里没有拷贝函数,而是指向它,有什么不一样呢? 这个 onclick 属性没有包含实际函数,而只是一个函数调用。

doSomething();

上面的意思是:“到 doSomething() 那里去执行它”。在doSomething()里面,this 关键字再次指向全局 window 对象,那么函数会返回错误的消息。

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

不一样?

如果是用 this 去访问 HTML 元素来处理事件的话,那么必须肯定它实际是写入了 onclick 属性中。而它指向 HTML 元素的事件处理就算已注册。如果这么做:

element.onclick = doSomething;
alert(element.onclick)

得到的是

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

可以看到,this 关键字在 onclick 方法中。它指向 HTML 元素。

但是如果这么做:

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

得到的是

function onclick()
{
	doSomething()
}

这里只是指向函数 doSomething()。this 关键字不在 onclick 方法中。它没有指向 HTML 元素。

例子-拷贝

在下面示例中,this 写入 onclick 方法中:

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

例子-指向

在下面示例中,this 指向 window:

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

要注意上面的 attachEvent。它的缺点是微软事件注册模型,它创建了指向该函数,而且没有拷贝它。所以有时不可能弄清楚 HTML 当前的处理事件是哪个。

结合

使用行内事件注册时,也可以把 this 发送到函数。所以可以这么用:

<element onclick="doSomething(this)">
 
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 = '#cc0000';
}
Javascript 相关文章推荐
javascript 10进制和62进制的相互转换
Jul 31 Javascript
详解Javascript动态操作CSS
Dec 08 Javascript
jQuery中triggerHandler()方法用法实例
Jan 19 Javascript
详解JavaScript中的自定义事件编写
May 10 Javascript
jQuery实现调整表格单列顺序完整实例
Jun 20 Javascript
微信小程序 小程序制作及动画(animation样式)详解
Jan 06 Javascript
JavaScript提高加载和执行效率的方法
Feb 03 Javascript
js实现HTML中Select二级联动的实例
Jan 05 Javascript
详解vue配置后台接口方式
Mar 29 Javascript
微信小程序实现pdf、word等格式文件上传的方法
Sep 10 Javascript
解决vue bus.$emit触发第一次$on监听不到问题
Jul 28 Javascript
vue3.0 数字翻牌组件的使用方法详解
Apr 20 Vue.js
一个JS小玩意 几个属性相加不能超过一个特定值.
Sep 29 #Javascript
IE FF OPERA都可用的弹出层实现代码
Sep 29 #Javascript
javascript 表单验证常见正则
Sep 28 #Javascript
javascript 页面划词搜索JS
Sep 28 #Javascript
jquery 模式对话框终极版实现代码
Sep 28 #Javascript
javascript的onchange事件与jQuery的change()方法比较
Sep 28 #Javascript
支持ie与FireFox的剪切板操作代码
Sep 28 #Javascript
You might like
ThinkPHP中实例Model方法的区别说明
2010/08/21 PHP
jQuery Autocomplete自动完成插件
2010/07/17 Javascript
基于jQuery的实现简单的分页控件
2010/10/10 Javascript
javascript + jquery实现定时修改文章标题
2014/03/19 Javascript
jquery常用特效方法使用示例
2014/04/25 Javascript
jquery实现的鼠标下拉滚动置顶效果
2014/07/24 Javascript
JavaScript插件化开发教程 (二)
2015/01/27 Javascript
jquery append 动态添加的元素事件on 不起作用的解决方案
2015/07/30 Javascript
延时加载JavaScript代码提高速度
2015/12/27 Javascript
体验jQuery和AngularJS的不同点及AngularJS的迷人之处
2016/02/02 Javascript
javascript创建对象的几种模式介绍
2016/05/06 Javascript
深入剖析JavaScript:Object类型
2016/05/10 Javascript
vue.js中$watch的用法示例
2016/10/04 Javascript
浅析script标签中的defer与async属性
2016/11/30 Javascript
详解JavaScript中数组的reduce方法
2016/12/02 Javascript
angularjs中的$eval方法详解
2017/04/24 Javascript
js实现延迟加载的几种方法详解
2019/01/19 Javascript
layui动态加载多表头的实例
2019/09/05 Javascript
微信小程序间使用navigator跳转传值问题实例分析
2020/03/27 Javascript
[42:56]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python logging模块学习笔记
2014/05/24 Python
简单谈谈Python中的闭包
2016/11/30 Python
11月编程语言排行榜 Python逆袭C#上升到第4
2017/11/15 Python
浅谈flask源码之请求过程
2018/07/26 Python
python实现两张图片拼接为一张图片并保存
2019/07/16 Python
Python 单例设计模式用法实例分析
2019/09/23 Python
将tensorflow.Variable中的某些元素取出组成一个新的矩阵示例
2020/01/04 Python
Linux安装Python3如何和系统自带的Python2并存
2020/07/23 Python
工作时间擅自离岗检讨书
2014/10/24 职场文书
2014年公务员转正工作总结
2014/11/07 职场文书
网络妈妈观后感
2015/06/08 职场文书
小学语文继续教育研修日志
2015/11/13 职场文书
pytorch 带batch的tensor类型图像显示操作
2021/05/20 Python
Mysql效率优化定位较低sql的两种方式
2021/05/26 MySQL
python 多态 协议 鸭子类型详解
2021/11/27 Python
python读取并查看npz/npy文件数据以及数据显示方法
2022/04/14 Python