全局数组返回undefined

时间:2014-04-05 06:48:35

标签: javascript variables closures

我有一个带有1,2,3,4按钮的幻灯片。我还定义了一个带有4个图像网址的数组。单击该按钮时,它将调用特定的相应URL。

<div id="slideshow">
<div id="source"><img src="images/blue.jpg">
<ul id="controller">
<li class="button">1</li>
<li class="button">2</li>
<li class="button">3</li>
<li class="button">4</li>
</ul>
</div>
</div>

使用Javascript:

var button=document.getElementsByClassName("button")
var image=document.getElementsByTagName("img")[0]
var sources=new Array("images/blue.jpg","images/red.jpg","images/yellow.jpg","images/green.jpg");

for (var i=0;i<sources.length;i++){
    button[i].onclick=function(){
            image.src=sources[i]
            }
}

但是当我点击按钮时,来源[i]总是返回undefined。

3 个答案:

答案 0 :(得分:0)

for (var i=0;i<sources.length;i++){
    button[i].onclick= function(i){
       return function(){
            image.src=sources[i]
            }
     }(i);
}

试试这个http://jsbin.com/puyipiro/1/

P.S。 onclick处理程序中的错误原因i等于4,因此必须使用创建处理程序

在每次迭代时保存当前值

答案 1 :(得分:0)

您遇到了JavaScript中最令人困惑的部分之一,即闭包捕获问题。要让你的代码重新编写,

var button=document.getElementsByClassName("button")
var image=document.getElementsByTagName("img")[0]
var sources=new Array("images/blue.jpg","images/red.jpg","images/yellow.jpg","images/green.jpg");

for (var i=0;i<sources.length;i++){
   (function (i) {
     button[i].onclick=function(){
       image.src=sources[i]
     }
   })(i);
}

这使用一个立即执行的函数来引入一个新的范围,因此每个onclick都有自己的i副本,在创建函数时它的值为i而不是共享相同的i,其值为sources.length

如果您定位支持ES 6的浏览器,则可以使用let代替var,然后允许您将其写为,

var button=document.getElementsByClassName("button")
var image=document.getElementsByTagName("img")[0]
var sources=new Array("images/blue.jpg","images/red.jpg","images/yellow.jpg","images/green.jpg");

for (var i=0;i<sources.length;i++){
  let j = i;
  button[i].onclick=function() {
    image.src=sources[j]
  }
}

let语句为循环中的每次迭代为j创建一个新的范围,因此j函数捕获的onclick不同并存储{的值{1}}当函数被创建为上面立即执行的函数时。

不幸的是,ES 6尚未广泛使用,因此我原始建议的一些变体就是您所需要的。

答案 2 :(得分:-1)

您可以将i值存储在适当的DOM元素(按钮)中,例如作为属性,然后在onclick处理程序中检索它们。不知怎的,这样:

for (var i=0;i<sources.length;i++){
    button[i].setAttribute('data-btn_i', i);
    button[i].onclick=function(){
        image.src=sources[this.getAttribute('data-btn_i')];
    }
}