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与JSONP轻松解决跨域访问的问题
Feb 04 Javascript
javascript实现删除前弹出确认框
Jun 04 Javascript
使用jquery插件qrcode生成二维码
Oct 22 Javascript
BootStrap+Angularjs+NgDialog实现模式对话框
Aug 24 Javascript
Bootstrap菜单按钮及导航实例解析
Sep 09 Javascript
详解Vue使用 vue-cli 搭建项目
Apr 20 Javascript
nginx配置React静态页面的方法教程
Nov 03 Javascript
vue 2.x 中axios 封装的get 和post方法
Feb 28 Javascript
js实现随机数小游戏
Jun 28 Javascript
微信小程序在ios下Echarts图表不能滑动的问题解决
Jul 10 Javascript
Laravel admin实现消息提醒、播放音频功能
Jul 10 Javascript
vue 内联样式style中的background用法说明
Aug 05 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
第六节--访问属性和方法
2006/11/16 PHP
php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法
2014/11/11 PHP
php获取远程文件的内容和大小
2015/11/03 PHP
PHP中PDO连接数据库中各种DNS设置方法小结
2016/05/13 PHP
js中substr,substring,indexOf,lastIndexOf的用法小结
2013/12/27 Javascript
JavaScript实现的简单拖拽效果
2015/06/01 Javascript
Javascript实现Array和String互转换的方法
2015/12/21 Javascript
jQuery插件制作的实例教程
2016/05/16 Javascript
JS Array创建及concat()split()slice()的使用方法
2016/06/03 Javascript
利用原生js和jQuery实现单选框的勾选和取消操作的方法
2016/09/04 Javascript
使用Javascript监控前端相关数据的代码
2016/10/27 Javascript
bootstrap按钮插件(Button)使用方法解析
2017/01/13 Javascript
javascript实现秒表计时器的制作方法
2017/02/16 Javascript
Vue 2.0在IE11中打开项目页面空白的问题解决
2017/07/16 Javascript
详解node服务器中打开html文件的两种方法
2017/09/18 Javascript
基于vue-cli配置lib-flexible + rem实现移动端自适应
2017/12/26 Javascript
微信小程序登陆注册功能的实现代码
2019/12/10 Javascript
[51:43]OG vs LGD 2018国际邀请赛淘汰赛BO3 第五场 8.26
2018/08/30 DOTA
Python socket C/S结构的聊天室应用实现
2014/11/30 Python
Python实现多线程HTTP下载器示例
2017/02/11 Python
python+matplotlib绘制旋转椭圆实例代码
2018/01/12 Python
Python基于csv模块实现读取与写入csv数据的方法
2018/01/18 Python
详解如何利用Cython为Python代码加速
2018/01/27 Python
Python Matplotlib实现三维数据的散点图绘制
2019/03/19 Python
Python 实现使用空值进行赋值 None
2020/03/12 Python
Ubuntu中配置TensorFlow使用环境的方法
2020/04/21 Python
Python如何解除一个装饰器
2020/08/07 Python
薇诺娜官方网上商城:专注敏感肌肤
2017/05/25 全球购物
预订奥兰多和佛罗里达州公园门票:FloridaTix
2018/01/03 全球购物
德国Discount-Apotheke中文官网:DC德式康线上药房
2020/02/18 全球购物
护理中职生求职信范文
2014/02/24 职场文书
海洋科学专业求职信
2014/08/10 职场文书
教育系统干部作风整顿心得体会
2014/09/09 职场文书
街道党风廉政建设调研报告
2015/01/01 职场文书
面试通知短信
2015/04/20 职场文书
2015年依法行政工作总结
2015/04/29 职场文书