此 Backbone TodoMVC 示例中的这些模式是什么

What are these patterns in this Backbone TodoMVC example

调查 todomvc backbone codes example。 js/中的结构 fold:

├── app.js
├── collections
│   └── todos.js
├── models
│   └── todo.js
├── routers
│   └── router.js
└── views
    ├── app-view.js
    └── todo-view.js

app.js

var app = app || {};
$(function () {
    'use strict';
    // kick things off by creating the `App`
    new app.AppView();
});

collections/todos.js

var app = app || {};

(function () {
    'use strict';
    var Todos = Backbone.Collection.extend({
    model: app.Todo,
    app.todos = new Todos();
})();

models/todo.js

var app = app || {};

(function () {
    'use strict';
    app.Todo = Backbone.Model.extend({
    });
})();

views/app-view.js

var app = app || {};
(function ($) {
    'use strict';
    app.AppView = Backbone.View.extend({
})(jQuery);

我有两个问题:

  1. 为什么每个文件中有 var app = app || {}

  2. $(function(){})(function(){})()(function($))(jQuery)有什么区别?

  1. app 变量是全局变量并封装了整个 Backbone 应用程序以最小化全局命名空间污染。 Here 您可以找到有关命名空间模式的更多详细信息。

    var app = app || {} 用新的空对象初始化全局 app 变量(如果尚未初始化)。不然就没动了。

  2. 函数:

    • $(function(){}) 是 jQuery 的 $(document).ready(function(){}) 的快捷方式。 Docs
    • (function(){})() 是一个 Immediately-invoked function expression (IIFE) 没有参数
    • (function($){ /* here $ is safe jQuery object */ })(jQuery) 是带有参数的 IIFE - jQuery 对象将作为 $ 传递给那个匿名函数

$(function() {
  console.log("Document ready event");
});

$(document).ready(function() {
  console.log("Document ready event");
});

(function() {
  console.log("Immediately-invoked function expression without parameters");
})();

(function($) {
  console.log("Immediately-invoked function expression with parameter. $ is a jQuery object here:");
  console.log($.fn.jquery);
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

虽然 解释了所有模式之间的区别,但缺少 "why" 您需要的这些。

命名空间和范围

以下模式的总体目标主要是命名空间和范围界定,具有不同的好处。避免污染全局命名空间是一种很好的做法,并且由于 JavaScript 没有将命名空间作为核心功能,因此出现了其他模式来解决这个问题。

How do I declare a namespace

全局命名空间

var app = app || {}; // if it doesn't exist yet, make it an new object.

为了避免污染全局命名空间(也就是使一切成为全局变量),您只创建一个变量,在您插入应用程序的所有其他模块。

然后,每个文件将其模块导出到唯一的全局变量中。

请注意,如果一个模块依赖于另一个模块,文件的顺序仍然很重要。

如果我们查看 TodoMVC example,它们按特定顺序包含文件:

<script src="js/models/todo.js"></script>
<script src="js/collections/todos.js"></script>
<script src="js/views/todo-view.js"></script>
<script src="js/views/app-view.js"></script>
<script src="js/routers/router.js"></script>
<script src="js/app.js"></script>

范围界定

假设您在一个文件中声明了 var test = 2;,它是一个在整个模块中使用的关键变量。然后,在另一个文件中,复制您在第一个模块中使用的良好模式。您刚刚覆盖了 test 变量,现在它在两个模块之间不由自主地共享。

为了使模块私有的局部函数和变量,您可以使用 Immediately-invoked function expression (IIFE). Block scoping 来限定它们的范围。Immediately-invoked function expression (IIFE). Block scoping 相对较新并且还没有得到很好的支持,所以最安全的方法是使用函数范围。

var app = app || {}; // global

(function () {
    // private to this scope
    var Todos = Backbone.Collection.extend({});

    // export the Todos constructor to the global app namespace
    app.Todos = Todos;

    function localFunction(param) { /** snip **/ }
})();