JavaScript:定义函数和实例化对象的顺序
我对定义函数和实例化对象的顺序有疑问,请参见: 我现在只是在玩弄一个想法,但我碰到了这堵墙,我不知道这个问题是否有简单的解决办法。基本上,我有一个对象,在另一个对象上有一些方法,但这个另一个对象包含对第一个对象的引用,因此无论我实例化/定义的顺序如何,我都会得到一个错误,因为其中一个没有加载:JavaScript:定义函数和实例化对象的顺序,javascript,Javascript,我对定义函数和实例化对象的顺序有疑问,请参见: 我现在只是在玩弄一个想法,但我碰到了这堵墙,我不知道这个问题是否有简单的解决办法。基本上,我有一个对象,在另一个对象上有一些方法,但这个另一个对象包含对第一个对象的引用,因此无论我实例化/定义的顺序如何,我都会得到一个错误,因为其中一个没有加载: var router = { update: function(event, from, to) { window.location.hash = "#/" + to;
var router = {
update: function(event, from, to) {
window.location.hash = "#/" + to;
$("back-btn").disabled = fsm.can("back"); // *** And here I am referencing fsm
$("next-btn").disabled = fsm.can("next");
},
location: window.location.hash.substring(2),
}
var fsm = StateMachine.create({
initial: "intro",
events: [
// Next events and where to route based on our page
{ name: "next", from: "intro", to: "getname" },
{ name: "next", from: "getname", to: "welcome" },
{ name: "next", from: "welcome", to: "why" },
// We can't go "back" from the initial route
{ name: "back", from: "getname", to: "intro" },
{ name: "back", from: "welcome", to: "getname" },
{ name: "back", from: "why", to: "welcome" } ],
callbacks: {
onintro : router.update, //*** Here I am referencing the router object
ongetname: router.update,
onwelcome: router.update,
onwhy : router.update
}
});
感谢您的帮助。出现时间问题似乎是因为您指定的回调之一是
onintro
,它可能会立即运行。为onintro
回调重构实现是否可行?您可能可以通过以下方式逃脱:
var router = {
update: function(event, from, to) {
window.location.hash = "#/" + to;
$("back-btn").disabled = fsm.can("back");
$("next-btn").disabled = fsm.can("next");
},
location: window.location.hash.substring(2),
}
var fsm = StateMachine.create({
//...
callbacks: {
//onintro : router.update, // Don't call this in the constructor...
ongetname: router.update,
onwelcome: router.update,
onwhy : router.update
}
});
router.update(); // Call it just after construct.
您可以使用
try/catch
来避免第一个未定义的:
try {
$("back-btn").disabled = fsm.can("back");
$("next-btn").disabled = fsm.can("next");
} catch(e){}
此外,如果您在JSFIDLE中测试所有内容,它将把您的JS包装到一个
window.onload
函数中。因此,当您单击按钮时,它们将尝试调用fsm.back()
或fsm.next()
,其中fsm
是在窗口.onload
函数的范围内定义的。不在这些按钮可以访问的范围内。我必须在事件发生后将回调分配给状态机对象,然后将初始化推迟到定义路由器对象之后:
var fsm = StateMachine.create({
//*** Here we set defer to true
initial: { state: "intro", event: "init", defer: true },
events: [
// Next events and where to route based on our page
{ name: "next", from: "intro", to: "getname" },
{ name: "next", from: "getname", to: "welcome" },
{ name: "next", from: "welcome", to: "why" },
// We can't go "back" from the initial route
{ name: "back", from: "getname", to: "intro" },
{ name: "back", from: "welcome", to: "getname" },
{ name: "back", from: "why", to: "welcome" } ],
});
window.onload = function() {
var router = {
update: function(event, from, to) {
window.location.hash = "#/" + to;
$("back-btn").disabled = fsm.cannot("back");
$("next-btn").disabled = fsm.cannot("next");
},
location: window.location.hash.substring(2),
}
//*** And now we attach the callbacks since we have created the router object
fsm.onintro = router.update, fsm.ongetname = router.update,
fsm.ongetname = router.update, fsm.onwelcome = router.update,
fsm.onwhy = router.update;
//*** And call the init event!
fsm.init();
}
依赖项修复可以简单到:
var router = {
update: function(event, from, to) {
window.location.hash = "#/" + to;
if(window.fsm) {
$("back-btn").disabled = fsm.can("back");
$("next-btn").disabled = fsm.can("next");
}
},
location: window.location.hash.substring(2),
}
还有可能重复,这里有一个关于require.js的好问题需要检查。您是在JSFIDLE的范围内完成这些工作,还是在其他地方进行测试?我在没有JSFIDLE的浏览器中进行测试。。。看起来像是黑客,不是吗我最近的编辑对你不起作用吗?它实际上会在它尝试回调之前抛出错误,所以当我对它进行注释时,它会给出一个错误,这里有一个更为JSFIDLE友好的JSFIDLE,它的新版本可以工作:啊,如果我这样做了,按钮将被启用,并允许用户在不应该的时候最初访问back按钮。感谢所有的帮助/想法,但似乎我不得不推迟初始化FSM,分配回调,然后初始化FSM,这是迄今为止我看到的唯一没有bug的方法。不管怎样,这只是为了测试一个想法,没有什么东西能吸引广泛的观众(我不这么认为!)