JavaScript:定义函数和实例化对象的顺序

3
我在定义函数和实例化对象的顺序方面遇到了问题,请参见:JSFiddle 我现在只是在尝试一个想法,但我遇到了这个问题,我不知道是否有任何简单的解决方法。基本上,我有一个包含一些方法的对象,另一个对象包含对第一个对象的引用,所以无论我实例化/定义的顺序如何,都会出现错误,因为其中一个还没有被加载:
  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 
    }
  });

感谢您的任何帮助。

1
可能是重复的 https://dev59.com/tHM_5IYBdhLWcg3wRw11。此外,这里有一个关于 require.js 的好问题可供参考 https://dev59.com/lmjWa4cB1Zd3GeqPv_o3。 - mrk
你是在 JSFiddle 的范围内完成这一切,还是在其他地方进行测试? - daleyjem
我正在浏览器中进行测试,而不是在JSFiddle范围内。 - nak
4个回答

1
看起来时序问题出现的原因是您指定的回调函数之一是 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.

它实际上在尝试回调之前就抛出了错误,因此当我将其注释掉时,它会报错。这里有一个更适合JSFiddle的新版本的JSFiddle:http://jsfiddle.net/Yqdj5/1/ - nak

1
您可以使用 try/catch 来避免第一个 undefined:
try {
    $("back-btn").disabled = fsm.can("back");
    $("next-btn").disabled = fsm.can("next");
} catch(e){}

此外,如果您在JSFiddle中进行全部测试,则会将您的JS包装到window.onload函数中。因此,当您单击按钮时,它们将尝试调用fsm.back()fsm.next(),其中fsm是在该window.onload函数的范围内定义的,而不是在这些按钮可以访问的范围内定义的。


1

事实上,我必须在事后将回调函数分配给状态机对象,然后延迟初始化直到路由器对象被定义:

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();
}

并且fiddle相关。


嗯...看起来像是黑客攻击,不是吗。=/ 我最近的编辑对你没有用吗? - wxactly

0

依赖项修复可能很简单:

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),
}

啊,如果我这样做的话,按钮会被启用并允许用户最初访问后退按钮,而此时他们不应该这样做。感谢所有的帮助/想法,但似乎我必须推迟初始化FSM,分配回调,然后初始化FSM,这是我目前看到的唯一方法,没有错误。反正这只是为了测试一个想法,不会影响广大受众(我认为!) - nak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接