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

时间:2013-02-10 00:55:05

标签: javascript

我遇到定义函数和实例化对象的顺序问题,请参阅: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 
    }
  });

感谢您的帮助。

4 个答案:

答案 0 :(得分: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.

答案 1 :(得分:1)

您可以使用try/catch来避免第一个未定义:

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功能的范围内定义的。不在这些按钮可以访问的范围内。

答案 2 :(得分: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

答案 3 :(得分: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),
}