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 easyui window 窗口关闭时的提示
Jun 22 Javascript
jQuery拖拽div实现思路
Feb 19 Javascript
javascript实现图片循环渐显播放的方法
Feb 24 Javascript
Position属性之relative用法
Dec 14 Javascript
javascript+css3 实现动态按钮菜单特效
Feb 06 Javascript
一波JavaScript日期判断脚本分享
Mar 06 Javascript
微信小程序的日期选择器的实例详解
Sep 29 Javascript
vue 2.0 购物车小球抛物线的示例代码
Feb 01 Javascript
Vue+webpack项目基础配置教程
Feb 12 Javascript
详解Vue 全局引入bass.scss 处理方案
Mar 26 Javascript
angular4+百分比进度显示插件用法示例
May 05 Javascript
微信小程序仿淘宝热搜词在搜索框中轮播功能
Jan 21 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
PHP 获取指定地区的天气实例代码
2017/02/08 PHP
js资料prototype 属性
2007/03/13 Javascript
js类中获取外部函数名的方法与代码
2007/09/12 Javascript
js中的scroll和offset 使用比较的实例与分析
2013/09/29 Javascript
onkeyup,onkeydown和onkeypress的区别介绍
2013/10/21 Javascript
JavaScript 动态加载脚本和样式的方法
2015/04/13 Javascript
JSON字符串转JSON对象
2015/07/31 Javascript
JS数组合并push与concat区别分析
2015/12/17 Javascript
jQuery简单实现彩色云标签效果示例
2016/08/01 Javascript
Bootstrap3 多选和单选框(checkbox)
2016/12/29 Javascript
JavaScript中创建对象的7种模式详解
2017/02/21 Javascript
轻松实现jQuery添加删除按钮Click事件
2017/03/13 Javascript
详解Vue 方法与事件处理器
2017/06/20 Javascript
jQuery实现的鼠标拖动浮层功能示例【拖动div等任何标签】
2018/12/29 jQuery
解决Vue使用bus总线时,第一次路由跳转时数据没成功传递问题
2020/07/28 Javascript
[59:07]海涛为你详解DOTA2新版本“贤哲秘契”
2014/11/22 DOTA
在漏洞利用Python代码真的很爽
2007/08/26 Python
Django 响应数据response的返回源码详解
2019/08/06 Python
python虚拟环境的安装和配置(virtualenv,virtualenvwrapper)
2019/08/09 Python
django自定义非主键自增字段类型详解(auto increment field)
2020/03/30 Python
pandas DataFrame 数据选取,修改,切片的实现
2020/04/24 Python
Python logging模块写入中文出现乱码
2020/05/21 Python
如何使用html5与css3完成google涂鸦动画
2012/12/16 HTML / CSS
香港草莓网土耳其网站:Strawberrynet TR
2017/03/02 全球购物
Mountain Warehouse德国官网:英国户外零售商
2019/08/11 全球购物
澳大利亚礼品篮网站:Macarthur Baskets
2019/10/14 全球购物
Shell编程面试题
2012/05/30 面试题
电信专业毕业生推荐信
2013/11/18 职场文书
作弊检讨书1000字
2014/02/01 职场文书
厨师个人自我鉴定范文
2014/04/19 职场文书
建筑工地宣传标语
2014/06/18 职场文书
2015年度党风廉政建设工作情况汇报
2015/01/02 职场文书
老公保证书怎么写
2015/02/26 职场文书
安全员岗位职责范本
2015/04/11 职场文书
2019暑假学生安全口号
2019/06/27 职场文书
90条交通安全宣传标语
2019/10/12 职场文书