3

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

  • The same thing it always does .. in the global scope it is a synonym for `window`. Using `call` then makes sure the `this` inside the function evaluates to the same object as the `this` outside .. –  Aug 10 '12 at 18:46
  • The "jQuery way" is generally `function ($) { .. }(jQuery)` to avoid `$` clashes, afaik. Perhaps it is preference or perhaps the code wasn't/isn't (always) in the same (global) context? –  Aug 10 '12 at 18:49
  • I don't understand what I am looking for in there :( –  Aug 10 '12 at 18:53
  • possible duplicate of [Why write ".call(this)" at the end of an javascript anonyms function?](http://stackoverflow.com/questions/8035822/why-write-callthis-at-the-end-of-an-javascript-anonyms-function) – DCoder Aug 12 '12 at 06:26

1 Answers1

6

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.

Kijewski
  • 25,517
  • 12
  • 101
  • 143