匿名函数中对变量的意外引用

时间:2012-06-14 17:09:33

标签: javascript

以下JavaScript有一些不需要的行为:

<html>
<script>
  function AddEventListener(el, listener)
  {
    el.addEventListener ? el.addEventListener('click', listener) : 
                          el.attachEvent('onclick', listener);
  }

  function Init(parent) 
  {
    var span = document.createElement("span");
    span.innerText = "Span1";

    AddEventListener(span, function() { alert(span.innerText); } ); 
    parent.appendChild(span);
    var span = document.createElement("span");

    span.innerText = "Span2";
    parent.appendChild(span);
  }
</script>
<body onload="Init(document.getElementById('drop'));">
  <div id='drop'></div>
</body>
</html>

如果点击Span1,警告窗口中会显示Span2。我理解为什么:javascript变量范围。但我不知道如何解决它。

某些上下文:我使用this.innerHTML,除了在IE8中工作正常。 this指向IE8中的窗口,而不指向事件侦听器的父窗口。

3 个答案:

答案 0 :(得分:2)

您可以使用传递给您注册的每个事件的event参数,而不是在单击回调中使用全局变量,然后使用其event.target参数来获取DOM元素参加了这次活动。

为此,您可以将注册的事件监听器更改为:AddEventListener(span,function(event) {alert((event.target ? event.target : event.srcElement).innerText);});

我在这里使用您的代码设置了一个示例:http://jsfiddle.net/dvirazulay/fTa6T/1/

答案 1 :(得分:2)

你可以返回一个函数而不只是声明一个函数,但我更喜欢@Dvir Azulay的建议:

function CreateAlert(span)
{
    return function() { alert(span.InnerText); };
}

function Init(parent) 
{
    var span=document.createElement("span");
    span.innerText="Span1";
    AddEventListener(span, CreateAlert(span)); 
    parent.appendChild(span);
    var span=document.createElement("span");
    span.innerText="Span2";
    parent.appendChild(span);
}

答案 2 :(得分:0)

试试这个:(将span的第二个定义更改为span2)

<!DOCTYPE html>
<html>
<script>

function AddEventListener(el,listener)
{
  el.addEventListener ? el.addEventListener('click', listener) :     el.attachEvent('onclick', listener);
}

function Init(parent) 
{
 var span=document.createElement("span");
 span.innerText="Span1";
 AddEventListener(span,function() {alert(span.innerText);}); 
 parent.appendChild(span);
 var span2=document.createElement("span");
 span2.innerText="Span2";
 parent.appendChild(span2);
}
</script>
<body onload="Init(document.getElementById('drop'));">
<div id='drop'></div>
</body>
</html>