21

我的 JavaScript 应用程序遇到了一个令人头疼的问题。

如果我写一个这样的元素:

<li onClick="alert(this.tagName)"></li>

我得到“LI”。

但是,如果我这样做:

<li onClick="foo()"></li>

其中“foo()”是:

function foo(){ alert(this.tagName); }

我得到“未定义”。

我不知道“这个”在附加功能方面应该如何工作。但是,我很困惑,因为“this”没有提取元素,而是显然默认为“window”。我无法弄清楚为什么会这样。

有人有解释吗?

4

5 回答 5

29

这是因为您没有在 JavaScript 函数调用中传递对this的引用。JavaScript 函数中的this引用的对象与onClick示例中的对象不同。试试这个:

 <li onClick="foo(this)"></li>

 function foo(item){ alert(item.tagName); }
于 2012-09-18T22:47:42.063 回答
4

在内联侦听器中:

> <li onClick="alert(this.tagName)"></li>

onclick 属性值有效地包装在一个函数中,并使用设置为 this 的元素调用,例如

function anon() {
  /* attribute value */
}

anon.call(element);

当你在 body 中放置一个函数时,你基本上得到:

function anon() {
  foo();
}

在这里,thiswithinanon将是元素,但由于foo在没有设置的情况下调用this,它将是未定义的。在非严格模式下,this将默认为全局对象(window在浏览器中)。在严格模式下,thisinsidefoo将是未定义的。

一种解决方案是将元素引用传递给函数:

<li onclick="foo(this)" ... >

然后在函数中:

function foo(callingElement) {
  ...
}

甚至:

<li onclick="foo.call(this)" ... >

function foo() {
  var callingElement = this;
}
于 2012-09-18T22:53:28.357 回答
2

正如其他答案已经提到的那样, 的值this将取决于如何调用包含它的函数。但是由于您的示例是关于事件处理程序的,所以我想强调 cjc343 在评论中所说的内容:

如果您删除内联事件处理程序,您可能会发现它更明智。

实际上,这很简单。考虑到这个 HTML:

<ul id="list">
    <li id="item1">item 1</li>
    <li id="item2">item 2</li>
    <li id="item3">item 3</li>
</ul>

以下 JavaScript 将说明删除内联处理程序和使用委托:

var list = document.getElementById('list');
list.addEventListener('click', function(evt){
    console.log("this is the element the event is bound to: " + this.id);
    console.log("the event target is the clicked element: " + evt.target.id);
});

http://jsfiddle.net/J3Gje/

这将适用于所有符合 W3C 事件模型的浏览器,包括 IE9。对于较旧的 IE,您必须使用attachEvent而不是addEventListener,并在事件名称前加上"on". 更多细节在这里

于 2012-09-18T23:17:59.140 回答
0

另一种选择是使用callapply,因此您不必将作为参数传递。这是一种在函数中设置this值的内置机制。虽然我要指出,将事件处理程序直接添加到 html 有点过时。您可能想查看用于事件委托的 JS 框架(jQueryPrototypeDojoYUI等)。

小提琴:http: //jsfiddle.net/bboone/Q2CkV/2/

HTML

<div onClick='alert(this.tagName);'>test</div>
<div onClick='foo.call(this);'>test2</div>​

JS

function foo(){ alert(this.tagName); }
于 2012-09-18T22:56:07.623 回答
-1

如果您是 JavaScript 新手,请不要使用thisornew关键字,否则您会弄错,或者您的代码会不必要地低效和复杂。但是,您要完成的工作如下:

<li onclick="foo(this)">some text</li>

在该示例中,该列表项的单击事件会触发一个名为 foo 的函数。关键字作为this变量传入。关键字仅指调用相关函数的this实体,如果找不到该实体,它将引用window浏览器的对象。在这种情况下,调用该函数的实体是 DOM 中的列表项节点。

我仍然建议永远不要使用this关键字,以避免这种混乱向前发展。

编辑:另外,不要使用 tagName 属性,因为这不是标准的。而是使用该nodeName属性。

于 2012-09-18T22:50:44.893 回答