Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Help understanding twitters widget.js file, a closure within a closure?

http://a2.twimg.com/a/1302724321/javascripts/widgets/widget.js?1302801865

It is setup like this at a high level:

public namespace:

TWTR = window.TWTR || {};

Then a closure:

(function() {
...

})(); // #end application closure

Within the application closure:

TWTR.Widget = function(opts) {
    this.init(opts);
};
(function() {
    // Internal Namespace.
    var twttr = {};
})();

Some methods are marked public, others private, and the only difference seems to be the naming convention (private starts with underscore '_').

Is it designed using the module pattern?

Why or what benefit do you get with a closure within a closure?

Since they load the widget.js before jquery, this means widget is designed to run w/o jquery since order matters correct?

Just trying to learn from this thing!

like image 926
Blankman Avatar asked Oct 11 '22 06:10

Blankman


1 Answers

It is setup like this at a high level:

public namespace:

TWTR = window.TWTR || {};

That is bad coding practice, variables should always be declared with var. And there are no "namespaces" in javascript, that term is applied to the above construct but it isn't really appropriate. Better to say its methods are contained by an object.

Then a closure:

> (function() { ...
> 
> })(); // #end application closure

That pattern has come to be called an immediately invoked function expression or iife. Not sure I like the name, but there you go. Anyway, it doesn't necessarily create any useful closures. A closure is only useful if a function creates variables that become bound to some other execution context that survives beyond the life of the function that created them (I hope that doesn't read like gobbledy-goop). You don't need an iife to create a closure.

However, you can use the above pattern to create closures since it's a function much like any other function.

Within the application closure:

> TWTR.Widget = function(opts) {
>     this.init(opts); }; (function() {
>     // Internal Namespace.
>     var twttr = {}; })();

Some methods are marked public, others private, and the only difference seems to be the naming convention (private starts with underscore '_').

The use of "public" and "private" are a bit misleading in javascript. The use of underscore to start identifer names indicates something that should only be used within the current scope, or by the "library" code itself. It's a bit redundant since the code should have a published API and any method that isn't part of the API shouldn't be avaialble externally.

But that is largely a matter of coding style and personal preference.

Is it designed using the module pattern?

Richard Cornford's "module pattern" is just that, a pattern. It's handy for simulating "private" variables in javascript, and also to share properties between functions or methods other than by the usual prototype inheritance. widget.js might be implemented (in parts) using the module pattern, but it it was likely designed by considering requirements and functionality. ;-)

Why or what benefit do you get with a closure within a closure?

Exactly the same benefits of any closure as stated above. Accessing variables essentially by placing them on an appropriate part of the scope chain is essentially the same as accessing properties via a [[prototype]] chain, only with (very different) mechanics - one uses identifier resolution on the scope chain, the other property resolution on the [[prototype]] chain.

Edit

One drawback is that the entire activation object that the closed variable belongs to is probably retained in memory, so if you just need access to a shared variable, better to consider some other scheme, perhaps even classic prototype inheritance. Or at least if you are going to use closures, try to keep the related activation object as small as reasonably possible (e.g. set any variables that aren't used to null just before exiting).

e.g.

var foo = (function() {

  // Variables available for closure
  var a, b, c;

  // Use a, b, c for stuff
  ...

  // Only want closure to c
  a = null;
  b = null;

  return function() {
    // use c
  }
}());

Since they load the widget.js before jquery, this means widget is designed to run w/o jquery since order matters correct?

I can't access the linked resource right now (corporate blocking of twitter domain), but the load order suggests you are correct. However, some code execution might be delayed until the document is fully loaded so it isn't a guaranteee, you'll need to look at the code.

like image 109
RobG Avatar answered Oct 19 '22 02:10

RobG