setTimeout()跳到数组的最后一个元素如何防止这种情况?

时间:2019-02-13 15:13:53

标签: javascript arrays

我正试图在JS上构建一个非常简单的交互式电影播放器​​,只是为了好玩。 wireTo(x)通过在相同索引上预定义的持续时间触发每个场景。 (这是我的期望)

我创建了一个循环,并将 setTimeout 函数放入其中。它在每个duration属性上都没有问题地进行迭代,但是不能使用name属性处理(跳转到最后一个属性)。

var MoviePlayer = (function() {

  function MoviePlayer(scenes) {
    this.setSource(scenes);
   
  }
  
  MoviePlayer.prototype.setSource = function(_scenes) {
    this.scenes = _scenes;
  }
  
  MoviePlayer.prototype.wireTo = function(number) {
    var parts = this.scenes[number].parts;
   
    for (var x in parts) { 
      var name = parts[x].name; // I think the problem starts here

      setTimeout(function() {
         alert(name); 
      }, parts[x].duration * x);
    }

  }
  
  return MoviePlayer;

}()); 


// scenes configuration json
var scenes = [
  {
    ep: 1,
    parts: [
      { name: "episode 1 p1", duration: 1000 },
      { name: "episode 1 p2", duration: 3000 }
    ],
    next: 2
  },
  {
    ep: 2,
    parts: [
      { name: "episode 2 p1", duration: 1000 },
      { name: "episode 2 p2", duration: 1000 }
    ],
    next: 3
   
  }
];

// instantiation
let player = new MoviePlayer(scenes);
player.wireTo(0);

我的逻辑有什么问题。任何帮助将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:0)

由于var的作用范围是该函数,因此您只有一个name变量,可用于循环中的每个迭代。因此,您将继续覆盖该变量,并且当计时器最终关闭时,它们都将看到您用其覆盖的最后一个值。

最简单的解决方法是只使用let而不是var。 let的作用域是块而不是函数,因此每次通过for循环时,您将拥有一个具有自己绑定的新变量。

for (let x in parts) { 
  let name = parts[x].name;

  setTimeout(function() {
     alert(name); 
  }, parts[x].duration * x);
}