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 相关文章推荐
jQuery的强大选择器小结
Dec 27 Javascript
Javascript学习笔记5 类和对象
Jan 11 Javascript
jquery中通过过滤器获取表单元素的实现代码
Jul 05 Javascript
jQuery的控件及事件(输入控件及回车事件)使用示例
Jul 25 Javascript
jquery datatable后台封装数据示例代码
Aug 07 Javascript
Node.js返回JSONP详解
May 18 Javascript
jQuery Easyui加载表格出错时在表格中间显示自定义的提示内容
Dec 08 Javascript
原生node.js案例--前后台交互
Feb 20 Javascript
vue v-model表单控件绑定详解
May 17 Javascript
JS实现返回上一页并刷新页面的方法分析
Jul 16 Javascript
微信小程序拼接图片链接无底洞深入探究
Sep 03 Javascript
利用H5api实现时钟的绘制(javascript)
Sep 13 Javascript
一个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
javascript实现动态CSS换肤技术的脚本
2007/06/29 Javascript
jQuery TextBox自动完成条
2009/07/22 Javascript
JavaScript 变量基础知识
2009/11/07 Javascript
Javascript中的相等与不等运算
2010/04/25 Javascript
鼠标滑上去后图片放大浮出效果的js代码
2011/05/28 Javascript
通过jQuery源码学习javascript(二)
2012/12/27 Javascript
js为鼠标添加右击事件防止默认的右击菜单弹出
2013/07/29 Javascript
CheckBoxList多选样式jquery、C#获取选择项
2013/09/06 Javascript
JavaScript版的TwoQueues缓存模型
2014/12/29 Javascript
读Javascript高性能编程重点笔记
2016/12/21 Javascript
js实现继承的方法及优缺点总结
2019/05/08 Javascript
解析JS在获取当前月的最后一天遇到的坑
2019/08/30 Javascript
浅谈vue异步数据影响页面渲染
2019/10/29 Javascript
Vue SSR 即时编译技术的实现
2020/05/06 Javascript
JS实现炫酷雪花飘落效果
2020/08/19 Javascript
Vue axios获取token临时令牌封装案例
2020/09/11 Javascript
js中实现继承的五种方法
2021/01/25 Javascript
[09:22]2014DOTA2西雅图国际邀请赛 主赛事第二日TOPPLAY
2014/07/21 DOTA
python搭建简易服务器分析与实现
2012/12/15 Python
python实现系统状态监测和故障转移实例方法
2013/11/18 Python
跟老齐学Python之使用Python查询更新数据库
2014/11/25 Python
用Python实现一个简单的线程池
2015/04/07 Python
利用Python中SocketServer 实现客户端与服务器间非阻塞通信
2016/12/15 Python
python删除本地夹里重复文件的方法
2020/11/19 Python
Python 实现「食行生鲜」签到领积分功能
2018/09/26 Python
使用Python的Turtle绘制哆啦A梦实例
2019/11/21 Python
关于numpy.where()函数 返回值的解释
2019/12/06 Python
django实现将后台model对象转换成json对象并传递给前端jquery
2020/03/16 Python
Django设置Postgresql的操作
2020/05/14 Python
Eyeko美国:屡获殊荣的睫毛膏、眼线笔和眉妆
2018/07/05 全球购物
英国汽车零件购物网站:GSF Car Parts
2019/05/23 全球购物
复核员上岗演讲稿
2014/01/05 职场文书
售后服务经理岗位职责
2014/02/25 职场文书
医院护士见习期自我鉴定
2014/04/10 职场文书
详解Oracle块修改跟踪功能
2021/11/07 Oracle
Nginx隐藏式跳转(浏览器URL跳转后保持不变)
2022/04/07 Servers