How to force jQuery.extend deep recursion

jQuery.extend extends a target object with properties from other objects and it’s widely used in every piece of jQuery code.

Really it’s very useful and simple to undestand and use for flat properties.

{[ .extend-flat | @how-to-highlight-code-in-wordpress.hilite( =javascript= ) ]}

On the contrary, if the involved objects have object properties, jQuery.extend is less intuitive and less useful too.

{[ .extend-object | @how-to-highlight-code-in-wordpress.hilite( =javascript= ) ]}

Luckily, an undocumented feature (deep) makes jQuery.extend recurr object properties.

{[ .extend-deep-std | @how-to-highlight-code-in-wordpress.hilite( =javascript= ) ]}

Unluckily, deep only works for the first level. (not really a ‘bug’)

{[ .extend-deep-bug | @how-to-highlight-code-in-wordpress.hilite( =javascript= ) ]}

If you need deep recursion use jQuery.extend_deep instead.

{[ .extend-deep-fix | @how-to-highlight-code-in-wordpress.hilite( =javascript= ) ]}

Here is the jQuery.extend_deep plugin:

{[ .extend-deep-plugin | @how-to-highlight-code-in-wordpress.hilite( =javascript= ) ]}

Scripting on the Moon

Ideally, an application, library, component, or widget defines only a single global variable. That variable should be an object which contains and is the root namespace for all of your stuff. (Douglas Crockford, Global Domination)

JavaScript libraries like YUI, Prototype, and jQuery, all follow a common pattern when it comes to the declaration of the namespace the library is built upon. They prefix the namespace variable with the var keyword, as here:

{[.declaration /enzymes/chili-js.php]}

I think they are wrong, because the var keyword is used for declaring local variables. It usually works fine because the root script (the file which defines the namespace, like yahoo.js) is usually loaded directly into an HTML page, so the local context where it is evaluated is the JavaScript global object.

But if it’s not the case, maybe because I’m using a different method to load the root script, then the library’s namespace could get declared in a local context which is different from the JavaScript global object and it won’t be global as expected by library’s users.

It could be argued that the method used to load the script root is flawed: it should evaluate any loaded script in the global context. But I think that this is a weak argument: a library’s namespace is intended to be global, no matter where the script is evaluated.

Using a platform library for web programming is like buying a superpod for watching tv programs. If I’m on the Earth all goes as expected, but what if I move to the Moon? On the Moon I’d want to turn the superpod on and watch Lost and Prison Break. (No news please, I’m on the Moon.) Anyway I’d get very angry if that super gadget could only tune lunar garbage.

JavaScript doesn’t have a global construct, because it implements implied globals, i.e. any variable defined without the var keyword is considered global. Douglas Crockford doesn’t like implied globals, and JSLint points them out because they could be a mistake, but they are really the only available method to make a variable global.

Lunar YUI
works fine if you execute YAHOO = {}; before loading the root script
Lunar Prototype
doesn’t work
Lunar jQuery
doesn’t work

Javascript Zombies

Javascript examples tend to zombify quite fastly. It’s pretty easy to make up a page for showing something, but very soon that page becomes unusable. I’m constantly finding many broken javascript examples in the internet.

And the semantic of a broken javascript example is a logic problem nobody can solve. Is it broken by accident or on purpose? Was it already broken when created? Who, what, where, when did it break? Is it a browser test? Am I doing something wrong?

Maybe we should refrain from presenting online examples.