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:
why var app = app || {}
in each file?
What are the differences between $(function(){})
, (function(){})()
, and (function($))(jQuery)
?
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 **/ }
})();