如何使用控制器范围的版本来引用JS中的当前控制器?

时间:2016-07-29 10:48:01

标签: javascript jquery

我遇到了以下问题。我的JavaScript结构如下所示。

我创建了一个包含所有控制器的对象。那些控制员有自己的责任。下面的代码属于首先调用的main.js文件:

main.js

var App = {};

App.init = function() {

    console.log('init');

    App.uiController.init();
    App.heroController.init();

}

在函数init()中,我调用控制器的初始化器。

控制器对象如下所示:

uiController.js

App.uiController = {

    root: 0,
    init: function() {

        // Development
        console.log('init uiController');

        root = this;

        // Call functions
        root.doSomething();

    },

    doSomething: function() {

    }
}

加载完所有脚本后,我调用最后一个脚本init.js

init.js

App.init();

我的HTML标记如下所示:

<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
</head>

<body>

    <!-- // Start HTML \\ -->
    <header id="header">
    </header><!-- End header#header -->

    <main class="main">     
    </main><!-- End main.main -->

    <footer id="footer">
    </footer><!-- End footer#footer -->



    <!-- JavaScript -->
    <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
    <script src="scripts/main.js" type="text/javascript"></script>

    <script src="scripts/constructors/uiController.js" type="text/javascript"></script>
    <script src="scripts/constructors/heroController.js" type="text/javascript"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
    <script src="scripts/init.js" type="text/javascript"></script>

</body>
</html>

在函数中,我使用root选择this - 我当前所在的文件。通常我会在每个函数(作用域)中创建变量root,并为其赋值this。但我认为这可能会更好,在每个控制器对象中创建一个空根(全局),所以我只创建一次值root,如下所示:

App.uiController = {

    root: 0,
    init: function() {

        root = this;

        // Call functions
        root.doSomething();

    },

    doSomething: function() {

    }
}

当我在root函数中的console.log init()时,它将返回一个对象,其中包含我现在所在的当前控制器中的所有函数,在上面的例子中App.uiController 。所以我认为这很有效,我只需为每个控制器创建并声明root一次。所以我对heroController执行了与uiController相同的操作,并将变量root记录到控制台。我接收到具有正确功能的不同对象:

enter image description here

但是,问题来了。在main.js我在heroController.init()之后调用uiController.init()并且当uiController由控制器内的事件触发时,我在控制台中收到错误,uiController内的某些函数无法正常工作期望。

当我删除每个控制器中的全局root变量并在var root = this;之类的init控制器中声明它时,代码将再次起作用。

有谁知道为什么上述设置无法正常运作?

期待您的回复。

更新

根据Kingshuk basak的回答,我尝试了一些新的东西。以下是我的想法:

答案代码对我不起作用。它会给我错误:Uncaught ReferenceError: root is not defined。当我使用我的问题中的代码并将root: 0的{​​{1}}更改为heroController并将两者都记录到控制台时:1我得到console.log(App.uiController.root, App.heroController.root);和{控制台中的{1}}。将它放在两个代码中的位置无关紧要,其他值不会覆盖这些值。这让我觉得很奇怪。

然后我尝试在0中注释掉1,然后在heroController中注释掉console.log main.js。我得到的值是root,这是真的,但之后我在uiController.init() function之后直接设置0和console.log,值也是root = this;而不是root.root作为0对象。这使得它更加令人困惑,为什么this没有更改为对象而不是uiController。此外,当我在文件root中注释掉0后,孔代码中只有一个root。仅限heroController.init()的Console.log将按预期提供main.js对象。

最后,我也尝试了root这两个函数:

uiController

当我这样做时,init()的值对于每个控制器都是正确的,因为它将包含对象 - 该对象 - 其中包含所有相应的函数。但这会让我遇到与之前提到的相同的问题,即uiController没有按预期工作。

As you can see, both roots inside each controller as different functions

希望这能为每个人提供更多关于状态的信息,并为一个好的解决方案提供一些帮助!

2 个答案:

答案 0 :(得分:6)

摘要

root设置为控制器的属性,以免您不必在控制器方法中键入var root = this是没有用的。您应该在需要时var root = this,因为该属性最终不是var root = this的净收益。

解释

你得到的第一个answer是部分答案。 kingshuk basak是正确的,你正在做的是在全局空间中设置一个root变量。如果你这样做,请参阅:

function foo() {
  something =  1;
}

您正在全局空间中设置something。要使其成为您的函数的本地化,您需要var

function foo() {
  var something =  1;
}

第一个代码段中缺少var并不会使JavaScript将其解释为this.something,即使该函数是原型的一部分。

kingshuk basak建议您使用this将其作为控制器的一部分。这是有效的,但是你必须使用this 来访问它,因为这是JavaScript的工作方式。所以使用它的天真方式是:

uiController = {
  root: 0,
  init: function() {
    this.root = this;
    this.root.doSomething(); // You havve to use `this` here too!!
  },

  doSomething: function() {
     this.root.somethingElse();
  }
}

从你的问题所说,你只是想避免写var root = this。所以root永远不会改变。但想一想这一秒。

您正在做的是向root添加名为this的属性,该属性与this具有完全相同的值。要访问与root具有相同价值的this,您需要拥有this。因此,this.root没有充分理由存在。如上所述,如果您执行this.root = this,则每次访问都必须为this.root,这样您就不会明显减轻您的负担。不仅如此,执行this.root.foo()还需要执行额外的间接:root必须首先从this获取。

你可以这样做:

uiController = {
  root: 0,
  init: function() {
    var root = this.root = this;
    root.doSomething();
  },

  doSomething: function() {
     var root = this.root;
     root.somethingElse();
  }
}

但同样,这并没有减轻负担。

您应该在需要时var root = this

答案 1 :(得分:2)

原因很简单。 uiController的'root'变量被heroController过度写入,因为它们都在全局命名空间中声明。为uiController和heroController尝试不同的名称root1和root2,它可以正常工作。

注意:理想情况下,您不应该污染全局命名空间以避免此类问题。必要时使用闭包。

这就是你要做的事情:

uiController = {

    root: 0,
    init: function() {

         this.root = this;

        // Call functions
        root.doSomething();

    },

    doSomething: function() {

    }
}