我正在尝试在js上构建一个非常简单的交互式电影播放器,只是为了好玩。 wireTo(x)按照自己的持续时间触发每个场景,该持续时间在相同的索引上预定义。 (这是我的期望)
我创建了一个循环并将setTimeout函数放在其中。它在每个持续时间属性上迭代没有问题,但它无法处理名称属性(跳转到最后一个)。
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);
我的逻辑有什么问题。任何帮助将非常感激。谢谢。
因为var
s的范围是函数,所以你只有一个name
变量,你在循环中的每次迭代都会使用它。所以你继续覆盖变量,当计时器最终消失时,它们都会看到你用它覆盖的最后一个值。
最简单的解决方法是使用let而不是var。设为块而不是函数,所以每次通过for循环,你都会有一个带有自己绑定的新变量。
for (let x in parts) {
let name = parts[x].name;
setTimeout(function() {
alert(name);
}, parts[x].duration * x);
}