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 相关文章推荐
ExtJS GridPanel 根据条件改变字体颜色
Mar 08 Javascript
读jQuery之六 缓存数据功能介绍
Jun 21 Javascript
JavaScript中的函数嵌套使用
Jun 04 Javascript
jquery移动点击的项目到列表最顶端的方法
Jun 24 Javascript
javascript移动开发中touch触摸事件详解
Mar 18 Javascript
JavaScript实现输入框与清空按钮联动效果
Sep 09 Javascript
js实现自动图片轮播代码
Mar 22 Javascript
借助node实战JSONP跨域实例
Mar 30 Javascript
javaScript 连接打印机,打印小票的实例
Dec 29 Javascript
vue.js与后台数据交互的实例讲解
Aug 08 Javascript
element实现合并单元格通用方法
Nov 13 Javascript
浅谈vue权限管理实现及流程
Apr 23 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中文处理 中文字符串截取(mb_substr)和获取中文字符串字数
2011/11/10 PHP
php.ini-dist 和 php.ini-recommended 的区别介绍(方便开发与安全的朋友)
2012/07/01 PHP
destoon实现会员商铺中指定会员或会员组投放广告的方法
2014/08/21 PHP
PHP正则表达式替换站点关键字链接后空白的解决方法
2014/09/16 PHP
PHP递归遍历多维数组实现无限分类的方法
2016/05/06 PHP
laravel解决迁移文件一次删除创建字段报错的问题
2019/10/24 PHP
var与Javascript变量隐式声明
2009/09/17 Javascript
使用JavaScript switch case 另类写法
2010/03/14 Javascript
手机平板等移动端适配跳转URL的js代码
2014/01/25 Javascript
浏览器中url存储的JavaScript实现
2015/07/07 Javascript
javascript实现点击单选按钮链接转向对应网址的方法
2015/08/12 Javascript
理解JS事件循环
2016/01/07 Javascript
纯js实现瀑布流布局及ajax动态新增数据
2016/04/07 Javascript
js数组的五种迭代方法及两种归并方法(推荐)
2016/06/14 Javascript
AngularJS实现路由实例
2017/02/12 Javascript
JQ中$(window).load和$(document).ready区别与执行顺序
2017/03/01 Javascript
使用Vue构建可重用的分页组件
2018/03/26 Javascript
vue组件文档(.md)中如何自动导入示例(.vue)详解
2019/01/25 Javascript
NodeJS读取分析Nginx错误日志的方法
2019/05/14 NodeJs
解决Vue中使用keepAlive不缓存问题
2020/08/04 Javascript
推荐下python/ironpython:从入门到精通
2007/10/02 Python
jupyter notebook引用from pyecharts.charts import Bar运行报错
2020/04/23 Python
Python使用gRPC传输协议教程
2018/10/16 Python
python list格式数据excel导出方法
2018/10/31 Python
在python中使用nohup命令说明
2020/04/16 Python
详解python UDP 编程
2020/08/24 Python
简单聊聊H5的pushState与replaceState的用法
2018/04/03 HTML / CSS
奥地利领先的在线药房:SHOP APOTHEKE
2019/10/07 全球购物
银行实习鉴定
2013/12/13 职场文书
2014的自我评价
2014/01/13 职场文书
旅游个人求职信范文
2014/01/30 职场文书
求职面试个人自我评价
2014/02/28 职场文书
庆元旦演讲稿
2014/09/15 职场文书
个人租房协议书范本
2014/09/30 职场文书
个人查摆剖析材料
2014/10/04 职场文书
CSS link与@import的区别和用法解析
2023/05/07 HTML / CSS