首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Backbone.js中将变量赋值给窗口对象

问在Backbone.js中将变量赋值给窗口对象
EN

Stack Overflow用户
提问于 2012-09-06 16:49:36
回答 3查看 4.3K关注 0票数 4

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

代码语言:javascript
复制
window.app = ( window.app || {} );

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

代码语言:javascript
复制
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中的对象?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-07 14:50:24

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

代码语言:javascript
复制
app = (app || {} );
app.Task = Backbone.Model.extend({ /*...*/ });
app.Tasks = Backbone.Collection.extend({ Model:app.Zask }); 

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

models/Task.js

代码语言:javascript
复制
define(function () {
  return Backbone.Model.extend({ /*...*/ });
});

collections/Tasks.js

代码语言:javascript
复制
define([models/Task], function (Task) {
  return Backbone.Collection.extend({ Model:app.Task }); 
});

app.js

代码语言:javascript
复制
define([collections/Tasks], function (Tasks) {
  var tasks = new Tasks();
  tasks.fetch();
});
票数 6
EN

Stack Overflow用户

发布于 2012-09-06 23:57:57

我不同意全局变量在javascript中不好的说法;在大多数语言中都需要全局变量。在导入某些内容之后,您需要能够引用它。类Java语言只是将所有类名放到某个巨大的全局堆中;但您永远不会意识到这一点,因为在这些语言中,类(类名、类引用)不是变量。

在javascript中,类(或者伪装成模拟类的东西)只是对象,你可以将其赋值给变量。因此,您需要确保可以在代码的其他部分引用它们。

现在,实际上在您的示例中,您将一个模型定义和一个集合实例(假设是单例)分配给全局作用域。对于模型定义,我认为这是正确且唯一的方法(也许可以添加一些名称空间,比如window.app.model.Task = Task)。在第二种情况下,纯粹主义者的观点可能是它不是那么好。我更喜欢做一些像window.app.collection.Tasks = Tasks这样的事情,然后定义一个静态方法Tasks.getinstance(),它返回单例。或者,将单例放在全局作用域以及window.app.singletons.Tasks = Tasks()中也不太好(但编码更少)。

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

代码语言:javascript
复制
(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));
票数 1
EN

Stack Overflow用户

发布于 2012-09-07 13:41:10

我个人不会污染与AMD解决方案类似的全局命名空间。这里有一篇关于sharing resources across AMD modules的文章,它基本上就是你想要做的,但是有一个模型和集合。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12296302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档