【问题标题】:Assigning variables to the window object in Backbone.js在 Backbone.js 中将变量分配给窗口对象
【发布时间】:2012-08-31 01:12:28
【问题描述】:

我正在开发一个大型 Backbone.js 应用程序。该代码使用require.js 模块化结构。 现在我看到很多主干代码和教程都是这样做的:

window.app = ( window.app || {} );

在他们将模型定义和 Collection 实例分配给该全局对象之后,如下所示:

Task = Backbone.Model.extend({ /*...*/ });
Tasks = Backbone.Collection.extend({ /*...*/ }); 

window.app.Task = Task;
window.app.Tasks = new Tasks();
// do this with all your models and collections

我喜欢这种方法,因为它简单且无需处理实例化集合的地点和时间。但是,首先使用require.js 将代码分成微小的位,然后将所有代码一起分配给全局变量(除了全局变量在javascript中通常是不好的代码样式),这似乎是错误的。

那么您对此有何看法,这种方法的优缺点是什么?您如何处理 Backbone 中的对象?

【问题讨论】:

    标签: javascript backbone.js requirejs


    【解决方案1】:

    首先,污染全局名称空间并不是什么大问题,因为您可以将所有模型包装在自己的名称空间中:

    app = (app || {} );
    app.Task = Backbone.Model.extend({ /*...*/ });
    app.Tasks = Backbone.Collection.extend({ Model:app.Zask }); 
    

    当涉及到 requirejs 时,它取决于您项目的大小。我认为对于较小的项目,你可以不用。使用 requirejs 的好处不是防止命名空间污染,而是更好的可维护性,因为您总是可以看到模块的依赖关系。你可以编写更好的单元测试,因为你可以测试一个模块和mock out all its dependencies。因此,我们将一个大型 Backbone 应用程序从上述示例的结构重建为如下所示:

    models/Task.js

    define(function () {
      return Backbone.Model.extend({ /*...*/ });
    });
    

    collections/Tasks.js

    define([models/Task], function (Task) {
      return Backbone.Collection.extend({ Model:app.Task }); 
    });
    

    app.js

    define([collections/Tasks], function (Tasks) {
      var tasks = new Tasks();
      tasks.fetch();
    });
    

    【讨论】:

    • 在 requirejs 中仍然使用app 变量是否是常规的?
    【解决方案2】:

    我个人不会污染与 AMD 解决方案类似的全局命名空间。这是sharing resources across AMD modules 上的帖子,这基本上是您想要做的,但带有模型和集合。

    此外,在这个用于 Backbone Aura 框架的 issue 的底部,有一个数据模块的实现,它对集合和模型进行命名空间以供检索。前几天我刚刚在我的应用程序中遇到了这个问题,这就是我计划实施的。

    【讨论】:

      【解决方案3】:

      我不同意全局变量在 javascript 中不好;大多数语言都需要全局变量。导入某些内容后,您需要能够引用它。类似 Java 的语言只是把所有的类名扔到一个巨大的全局堆上;但你从来没有意识到这是因为在那些语言中,类(类名、类引用)不是变量。

      在 javascript 中,类(或假装模仿类)只是对象,您将其分配给变量。因此,您可以确保可以在代码的其他部分引用它们。

      现在,实际上在您的示例中,您将模型定义和集合实例(可能是单例)分配给全局范围。对于模型定义,我会说这是正确且唯一的方法(也许添加一些命名空间,例如window.app.model.Task = Task)。在第二种情况下,纯粹主义者的观点可能是它不是那么好。我宁愿做window.app.collection.Tasks = Tasks之类的事情,然后定义一个静态方法Tasks.getinstance(),它返回单例。或者,不太好(但编码更少)是将您的单例也放在全局范围内window.app.singletons.Tasks = Tasks()

      最后,确保(我相信你已经做到了)所有这些都在适当的范围内。此代码(在浏览器中运行)还将使 Task 和 Tasks 成为全局对象。将整个事情包装在一个函数中,并使用var

      (function (app) {
        var Task = Backbone.Model.extend({ /*....*/ }),
        Tasks = Backbone.Collection.extend({ /*....*/ }, {
          getInstance: function () {
            if (!this.instance) {
              this.instance = new Tasks();
            }
            return this.instance;
          }
        });
      
        if (!app.models) {
          app.models = {};
        }
        if (!app.collections) {
          app.collections = {};
        }
      
        app.models.Task = Task;
        app.collections.Tasks = Tasks;
      }(window.app));
      

      【讨论】:

        猜你喜欢
        • 2019-03-20
        • 2018-10-26
        • 1970-01-01
        • 2012-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多