Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
625 views
in Technique[技术] by (71.8m points)

javascript - What are these patterns in this Backbone TodoMVC example

Looking into the todomvc backbone codes example. The structure in the 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);

I have two questions:

  1. why var app = app || {} in each file?

  2. What are the differences between $(function(){}), (function(){})(), and (function($))(jQuery)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

While Yurii explained the difference between all the patterns, it's missing the "why" you would need these.

Namespacing and scoping

The overrall goal of the following patterns is mostly namespacing and scoping, with different benefits. It's a good practice to avoid polluting the global namespace, and since JavaScript doesn't have namespace as a core feature, other patterns have emmerged to solve that.

See How do I declare a namespace.

Global namespace

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

In order to avoid polluting the global namespace (AKA making everything a global variable), you create only one variable, inside of which you insert every other modules of your app.

Then, each file exports its module into that sole global variable.

Note that the order of the files is still important if a module depends on another.

If we look at the TodoMVC example, they included the files in a specific order:

<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>

Scoping

Imagine you declared var test = 2; in a file and it's a critical variable that is used throughout that module. Then, in another file, you copy the good pattern you were using inside the first module. You've just overriden the test variable and now, it is involontary shared between two modules.

In order to have local functions and variables private to a module, you can scope them with an Immediately-invoked function expression (IIFE). Block scoping is relatively new and not well-supported yet, so the safest way is to use the function scope.

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 **/ }
})();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...