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入门教程(12) js对象化编程
Jan 31 Javascript
RGB颜色值转HTML十六进制(HEX)代码的JS函数
Apr 25 Javascript
js常用排序实现代码
Dec 28 Javascript
通过action传过来的值在option获取进行验证的方法
Nov 14 Javascript
Jjcarousellite 实现图片列表滚动的简单实例
Nov 29 Javascript
jQuery采用连缀写法实现的折叠菜单效果
Sep 18 Javascript
js中flexible.js实现淘宝弹性布局方案
Jun 23 Javascript
Node.js操作Firebird数据库教程
Mar 04 Javascript
Listloading.js移动端上拉下拉刷新组件
Aug 04 Javascript
js实现文字跑马灯效果
Feb 23 Javascript
基于AngularJS实现表单验证功能
Jul 28 Javascript
jquery-file-upload 文件上传带进度条效果
Nov 21 jQuery
一个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
黑夜路人出的几道php笔试题
2009/08/04 PHP
js+php实现静态页面实时调用用户登陆状态的方法
2015/01/04 PHP
JavaScript XML和string相互转化实现代码
2011/07/04 Javascript
javascript中动态加载js文件多种解决办法总结
2013/11/15 Javascript
ExtJS中设置下拉列表框不可编辑的方法
2014/05/07 Javascript
node.js操作mongodb简单示例分享
2017/05/25 Javascript
vue-cli脚手架config目录下index.js配置文件的方法
2018/03/13 Javascript
最后说说Vue2 SSR 的 Cookies 问题
2018/05/25 Javascript
Bootstrap Fileinput 4.4.7文件上传实例详解
2018/07/25 Javascript
jQuery实现的图片点击放大缩小功能案例
2020/01/02 jQuery
js实现适配移动端的拖动效果
2020/01/13 Javascript
python下函数参数的传递(参数带星号的说明)
2010/09/19 Python
举例讲解Python程序与系统shell交互的方式
2015/04/09 Python
Python 爬虫学习笔记之正则表达式
2016/09/21 Python
Python3.6安装及引入Requests库的实现方法
2018/01/24 Python
Django中的CBV和FBV示例介绍
2018/02/25 Python
Python字典的核心底层原理讲解
2019/01/24 Python
使用python turtle画高达
2020/01/19 Python
python GUI库图形界面开发之PyQt5计数器控件QSpinBox详细使用方法与实例
2020/02/28 Python
Python就将所有的英文单词首字母变成大写
2021/02/12 Python
基于ccs3的timeline时间线实现方法
2020/04/30 HTML / CSS
HTML5 visibilityState属性详细介绍和使用实例
2014/05/03 HTML / CSS
Styleonme中文网:韩国高档人气品牌
2017/06/21 全球购物
麦德龙官方海外旗舰店:德国麦德龙超市
2017/12/23 全球购物
几个判断型的面试题
2012/07/03 面试题
95%的面试官都会问到的50道Java线程题,附答案
2012/08/03 面试题
大学生志愿者感言
2014/01/15 职场文书
党日活动总结
2014/05/07 职场文书
食品安全演讲稿
2014/09/01 职场文书
机票销售员态度不好检讨书
2014/09/27 职场文书
2019年国庆祝福语(70句)
2019/09/19 职场文书
nginx配置之并发频次限制
2022/04/18 Servers
Flutter Navigator 实现路由传递参数
2022/04/22 Java/Android
pandas中pd.groupby()的用法详解
2022/06/16 Python
超越Nginx的Web服务器caddy优雅用法
2022/06/21 Servers
JS实现简单九宫格抽奖
2022/06/28 Javascript