this关键字
javascript最重要的关键字之一是this。但是如果你不了解它的工作原理使用起来就会很困难。
下面我将介绍在事件处理中如何运用它。以后我会增加this的其他用途。
所有者
这篇文章将要讨论的问题是:在函数doSomething()中this到底指向谁?
function doSomething() {
this.style.color = '#cc0000';
}
在javascript中,this始终指向我们正在执行的这个函数的“所有者”,或者更确切地说,函数是哪个对象的方法this就指向哪个对象。当我们在页面中定义函数doSomething()的时候,他的所有者就是这个页面,或者说javascript的window对象(或全局对象)。而一个onclick属性的所有者是它所在的HTML元素。
这种“所属关系”是javascript的面向对象特性造成的,欲了解更多信息请阅读这篇对象亦是关联数组。
------------ window -------------------------------------- | / \ | | | | | this | | ---------------- | | | | HTML 元素 | <-- this ----------------- | | ---------------- | | doSomething() | | | | | ----------------- | | -------------------- | | | onclick 属性 | | | -------------------- | | | ----------------------------------------------------------
如果我们直接执行doSomething(),那么this关键字指向window,并且函数会去改变window对象的style.color,由于window对象没有style属性,这个函数会执行失败,并产生js错误。
拷贝
如果我们要合理地运用this就必须确保使用它的函数为正确的HTML元素所拥有,或换一种说法,我们必须把函数拷贝到onclick属性上,传统的事件绑定模型很好地处理了这个问题。
element.onclick = doSomething;
函数被完整地拷贝到了onclick属性上(现在成了一个方法),所以当事件处理函数被执行的时候this指向HTML元素并且它的color会被改变。
------------ window -------------------------------------- | | | | | | | ---------------- | | | HTML元素 | <-- this ----------------- | | ---------------- | | doSomething() | | | | | ----------------- | | ----------------------- | | | |doSomething()的一份拷贝| <-- 拷贝函数 | | ----------------------- | | | ----------------------------------------------------------
这里有个小技巧是我们可以把函数拷贝到多个事件处理器上,每次this都能指向正确地HTML元素:
------------ window -------------------------------------- | | | | | | | ---------------- | | | HTML元素 | <-- this ----------------- | | ---------------- | | doSomething() | | | | | ----------------- | | ----------------------- | | | |doSomething()的一份拷贝| <-- 拷贝函数 | | ----------------------- | | | | | | ----------------------- | | | | 另一个HTML元素 | <-- this | | | ----------------------- | | | | | | | | | ----------------------- | | | |doSomething()的一份拷贝| <-- 拷贝函数 | | ----------------------- | | | ----------------------------------------------------------
这样才是比较充分地使用this,每次函数被执行的时候this都指向触发了这个事件的HTML元素,这个HTML元素“拥有”了doSomething()的一份拷贝。
调用
然而如果你使用行内事件绑定方式
<element onclick="doSomething()">
你没有拷贝函数!而是调用了这个函数。其中的区别是很关键的。这里的onclick属性并没有包含任何实际的函数,而只是一个触发了这个函数:
doSomething();
他只是说了句“找到doSomething()并执行它”,当我们找到doSomething()的时候this关键字再一次指向了全局的window对象,并且函数会返回错误提示。
------------ window -------------------------------------- | / \ | | | | | this | | ---------------- | | | | HTML元素 | <-- this ----------------- | | ---------------- | | doSomething() | | | | | ----------------- | | ----------------------- / \ | | | 找到doSomething() | | | | | 并执行它 | ---- 对函数的调用 | | ----------------------- | | | ----------------------------------------------------------
区别
如果你想通过this来获得触发了这个事件的HTML元素,就必须确保this关键字确实被写入到了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 = doSomething
element.addEventListener('click',doSomething,false)
element.onclick = function () {this.style.color = '#cc0000';}
<element onclick="this.style.color = '#cc0000';">
例子——调用
下面这些情况this指向window:
element.onclick = function () {doSomething()}
element.attachEvent('onclick',doSomething)
<element onclick="doSomething()">
注意这里出现了attachEvent(),微软事件绑定模型的一个严重的缺点是attachEvent()只建立了对函数的调用但没有拷贝。所以有些时候我们无法知道是哪个HTML元素触发了这个事件。
二者结合
当使用行内事件绑定方式时也可以把this传给函数,使你仍然可以在函数内部使用它:
<element onclick="doSomething(this)">
function doSomething(obj) {
// this出现在了事件处理器内并且传给了函数
// obj现在指向HTML元素,所以你可以做以下操作
obj.style.color = '#cc0000';
}
本文翻译自PPK的The this keyword。
这个在《JavaScript Dom 高级程序设计》里面讲的内容大致差不多。
“你没有拷贝函数!而是引用了这个函数”,这里用“引用”容易引起误解吧,应该是“调用”更好一点。
oldsha
10 Jan 10 at 5:33 pm
嗯,谢谢,的确是调用好一点,我来改一下。
admin
10 Jan 10 at 7:00 pm
I had a desire to start my own commerce, however I did not have enough amount of cash to do that. Thank God my close colleague told to take the business loans. Therefore I took the consolidation loans and made real my dream.
Patel19KATHRINE
26 Feb 10 at 8:53 pm
翻译得不错!华丽~
George Wing
27 Feb 10 at 11:56 am
解释的相对深刻
过路者
7 May 10 at 9:29 am
This is a good place I can not believe that I didn’t wander onto it before
earn points
16 Jun 10 at 9:11 pm