PPK 谈 JavaScript 的 this 关键字 [翻译] |
下面先讲如何在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; } |