我有一个简单的Javascript程序,用于在每个项目的指定时间内滚动文本项列表。大多数代码都正常工作,但是我的对象没有保留状态会遇到问题。
我有一个BuildManager对象,它加载一个构建(一组指令),然后重新组装一个时间delta和DOM对象的数组。稍后,按钮的单击功能可以引用此对象的实例,从而检查其当前构建。 BuildManager实例正在构建数组,但是当按钮调用的函数运行时,BuildManager实例会说它的数组长度为零。我知道这是范围或类似的问题,但我找不到哪里。在测试期间,我注意到如果我使数组全局而不是对象属性,那么它就可以工作,因为全局变量保留了修改。
TLDR: document.ready函数创建一个名为manager的Build Manager,并设置监听器。我单击#load-build-button,它在manager中成功创建了数组(已验证)。稍后我点击#start-build-button失败,因为当它调用manager.getNextStepStartingTime()时,管理器active_build的长度为0。
这里的代码简化为必要的:
var BuildManager = function() {
var current_array = [
[5, "This is the step with the number: 1"],
[10, "This is the step with the number: 2"],
[15, "This is the step with the number: 3"],
[25, "This is the step with the number: 4"],
[40, "This is the step with the number: 5"],
[45, "This is the step with the numberasdfadsfasdfasf: 6"],
[47, "This is the step with the number: 7"],
[49, "This is the step with the number: 8"],
[50, "This is the step with the number: 9"],
[60, "This is the step with the number: 10"],
[120, "This is the step with the number: 11"],
[130, "This is the step with the number: 13"],
[133, "This is the step with the number: 14"],
[135, "This is the step with the numbasdfasdfadsfasfder: 15"],
[137, "This is the step with the number: 16"],
[139, "This is the step with the number: 17"],
[145, "This is the step with the number: 18"]
];
this.active_build = [];
this.loadBuild = function() {
$(".build-item").remove();
this.active_build = [];
for (var i = 0, len = current_array.length; i < len; i++) {
$(".build-list").append("<div class='build-item'>" + current_array[i][1] + "</div>\n");
this.active_build.push([current_array[i][0], $(".build-item:contains('"+ current_array[i][1] +"')")]);
}
};
this.getNextStepStartTime = function() {
return this.active_build[0][0];
};
this.getNextStepHeight = function() {
return this.active_build[0][1].height;
};
this.completeStep = function() {
this.active_build.shift();
};
};
$(document).ready(function() {
/* Initialize Jquery items */
$("input[type=button]").button();
/* High level data because setInterval doesn't work with objects */
var total_time_passed = 0;
var manager = new BuildManager();
function timerFunction() {
/* If this isn't the first time here, we've just completed a step, so let the manager know */
if (total_time_passed > 0) {
manager.completeStep();
}
/* Find out how long until the next step is complete, and animate to it */
var time_to_next = manager.getNextStepStartTime()-total_time_passed;
if (time_to_next > 0) {
var build_list = $(".build-list");
var prev_pos = parseInt(build_list.css("margin-top"));
build_list.animate({marginTop: prev_pos - manager.getNextStepHeight()}, time_to_next*1000);
}
/* Set this function to run again once the target time has been reached */
total_time_passed += time_to_next;
setTimeout(timerFunction, time_to_next*1000);
}
function startBuild() {
timerFunction();
}
function stopBuild() {
//does nothing yet
}
/* Setup Click Handlers */
$("#load-build-button").click(manager.loadBuild);
$("#start-build-button").click(startBuild);
$("#stop-build-button").click(stopBuild);
});
答案 0 :(得分:3)
manager.loadBuild
是对函数的引用,该函数不包含有关manager
的信息。您需要将引用传递给绑定到范围的函数:
$("#load-build-button").click(manager.loadBuild.bind(manager));
或者,您可以在声明函数时绑定函数:
this.loadBuild = function() {
$(".build-item").remove();
this.active_build = [];
for (var i = 0, len = current_array.length; i < len; i++) {
$(".build-list").append("<div class='build-item'>" + current_array[i][1] + "</div>\n");
this.active_build.push([current_array[i][0], $(".build-item:contains('"+ current_array[i][1] +"')")]);
}
}.bind(this); // bound!