user656925
user656925

Reputation:

Wrapping Libraries | jQuery vs. Backbone

Here is the Backbone wrapper

(function(){
    // Backbone.js
}).call(this);

For comparison. Here is the jQuery wrapper:

(function( window, undefined ) {
    // jQuery.js
})( window );

Regarding the BackBone Wrapper:

I understand the need for a immediately invoked (via call) function expression - to provide privacy (encapsulation)

I understand why it is an anonymous function - to reduce global symbols.

However I don't understand what 'this' refers to? + Why the difference in wrappers?

Reference

MDN - this

Upvotes: 3

Views: 190

Answers (1)

Kijewski
Kijewski

Reputation: 26043

It helps preserving the value of this in the inner function.

A call to an unbound function* resets this to the global object, i.e window in case of a browser.

See this example:

(function () {
    alert("1: " + this); // this == myObject

    (function () {
        alert("2: " + this); // this == window
    })();

    (function () {
        alert("3: " + this); // this == myObject
    }).call(this);
}).call(myObject);

*) I.e. calling func() instead of obj.func(). this would become obj in the latter case.


First clarification:

In case of backbone.js the reason why they wrap their code in (function () {...}).call(this) is that this way you don't need to know the actual name of the global object (global in case of node.js).

See http://backbonejs.org/docs/backbone.html#section-4


Second clarification:

If the script is run by a browser, this is the same object as window if you are not in the call context of a bound function. In a standalone JS engine (node, rhino …) the global object is not named window but global.

The jQuery developers know you want to run their script in a browser, because you would have little fun with it if you don't have a document to manipulate in first place.

Backbone.js, like underscore.js, is general purpose so the developers do not know the name of the global object. And they don't care.

So when jQuery does

(function (window) {
    ...
})(window);

it could have been implemented this way too

(function () {
    var window = this;
    ...
}).call(window);

and because this===window

(function () {
    var window = this;
    ...
}).call(this);

Read the examples backwards to see what the backbone hackers did. (They call the global object root. You may want to read the annotated code.)

I for one would have chosen

(function (root) {
    ...
})(this);

but in the end it does not matter I guess.

Upvotes: 6

Related Questions