javascript 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对象,并且函数会返回错误提示。(chrome的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) (ie报错无法设置属性“color”的值: 对象为 null 或未定义)
<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

via:http://biaoge.me/2010/01/289

 有时出现错误:

Object [object DOMWindow] has no method ‘attachEvent’

This error occurs when trying bind an event, using window.attachEvent as a function, which only works in Internet Explorer.

Your code might look something like this:

var myFunction = function(){
  alert("foo");
}

window.attachEvent("onclick", myFunction);

To fix this, use the following code (remember to remove “on” from “onclick” etc):

var myFunction = function(){
  alert("foo");
}

window.addEventListener("click", myFunction,false);
要注意自己的代码到底运行在哪个浏览器上。

原文地址:https://www.cnblogs.com/youxin/p/2726893.html