I'm trying to learn advance JavaScript and some people suggested to learn from Backbone.js source code
(function(factory) {
//There are some lines of code here...
})(function(root, Backbone, _, $) {
//Many lines of code here
});
factory
in (function(factory)
, the root that is in (function(root, Backbone, _, $)
?You are looking at the AMD module pattern, which I wouldn't spend too much time focusing on. factory
is the function with "Many lines of code". The first function you encounter calls factory
after it loads Backbone's dependencies - underscore.js (_
) and jquery.js ($
). Think of it as a dependency-injection version of:
<script src="jquery.js"></script>
<script src="underscore.js"></script>
<script>
function Backbone() {
// do stuff that depends on underscore and jquery
}
</script>
Is the factory in (function(factory), the root that is in (function(root, Backbone, _, $)?
No, answered above
What is factory?
The guts of the Backbone library which is initialized once its dependencies are loaded
What is Backbone?
An empty object to start out with root.Backbone = factory(root, exports, _, $);
where exports is initialized to {}
for a given module
What is _?
The underscore.js library
What is $?
The jquery library
Let’s make it a bit easier by naming the anonymous functions.
(function definingFn(factory) {
//There are some lines of code here...
})(function factoryFn(root, Backbone, _, $) {
//Many lines of code here
});
It could also be written like this:
function definingFn(factory) {/* code here */}
function factoryFn(root, Backbone, _, $) {/* code here */}
definingFn(factoryFn);
So, definingFn
receives factoryFn
as named argument factory
. So factory
is factoryFn
, the function you pass to the first function as argument.
Then inside of the definingFn
, other variables you are asking about are being defined:
(function(factory) {
// Establish the root object, `window` (`self`) in the browser, or `global` on the server.
// We use `self` instead of `window` for `WebWorker` support.
var root = (typeof self == 'object' && self.self === self && self) ||
(typeof global == 'object' && global.global === global && global);
// Set up Backbone appropriately for the environment. Start with AMD.
if (typeof define === 'function' && define.amd) {
define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
// Export global even in AMD case in case this script is loaded with
// others that may still expect a global Backbone.
root.Backbone = factory(root, exports, _, $);
});
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
} else if (typeof exports !== 'undefined') {
var _ = require('underscore'), $;
try { $ = require('jquery'); } catch (e) {}
factory(root, exports, _, $);
// Finally, as a browser global.
} else {
root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
}
})(function(root, Backbone, _, $) {
// more code here
})
There are several conditions that detect the environment of this script and each invoke the factory
function with certain value.
Let’s review just the "browser" environment:
First line in definingFn
defines the root
, the global object. The library is using self
global object (read about it on MDN) in case of browser environment.
Then empty object is supplied as in place of Backbone
named argument, to use as a "namespace" to attach things defined in factoryFn
.
Then global variable for underscore
library, which uses _
as its name is passed.
Then there’s $
object, which can be jQuery, Zepto or Ender, one of these libs, which Backbone is using for event delegation and XHR.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With