How does jQuery protect overwriting jQuery and $

These variables are located immediately after defining a local copy of jQuery in the jQuery source.

// Map over jQuery in case of overwrite
_jQuery = window.jQuery

// Map over the $ in case of overwrite
_$ = window.$

One can read the comments and know the why... but

  • How do these lines of code do this?

  • Would adding something similar protect my personal namespace or is there more too it deeper in the source?

  • What is an example of something bad that could happen if this weren't in the source code?

Answers:

Answer

How does jQuery protect overwriting jQuery and $

It doesn't (but see below). If you load jQuery, and then load something else that writes something else to those symbols, they won't be associated with jQuery anymore. Example:

HTML:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/prototype/1/prototype.js"></script>

JavaScript:

window.onload = function() {
  // Outputs false, because Prototype has overwritten it
  display("Does $ === jQuery? " + ($ === jQuery));

  // Outputs true, because Prototype has overwritten it
  display("Does $('foo').id === 'foo'? " + ($('foo').id === 'foo'));

  function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = msg;
    document.body.appendChild(p);
  }
};?

Live copy

But, it does seem to preserve them. How?

The answer is closures. It has a local reference, inside its scoping function, which is unconnected to the global reference (the property on window), so internally it doesn't care whether you overwrite those symbols. Of course, you care, if you overwrite both $ and jQuery, because if you do you have no way of calling jQuery. :-) But if you only overwrite $, that's not a problem, just use jQuery or if you don't like typing that (and let's face it, it's awkward), do this:

(function($) {
    // Your usual jQuery code here using `$`,
    // this code runs immediately
)(jQuery);

...which shadows the $ symbol locally within the anonymous function (which is defined and called at the same time). jQuery makes this particularly easy if you're using its ready event:

jQuery(function($) {
    // Your usual jQuery code here using `$`,
    // this code runs when the DOM is ready (see
    // the `jQuery.ready` function).
});
Answer

If you look through the jquery.js file you will find that they start by saving the previous definition (line 31-32 v1.4.4):

// Map over the $ in case of overwrite
_$ = window.$,

Then if you call noConflict it just sets the value back (line 397-398)

noConflict: function( deep ) {
    window.$ = _$;

You can add something similar to your own project to protect the name space. The concept holds for more than just javascript.

If these lines were not included, then you wouldn't be able to run jQuery and Prototype on the same page as both use the $ operator - nothing bad may happen, it's just that your code won't work and possibly cause errors.

Answer

If you were to include another library like prototype, which uses $, then jQuery needs to have a reference of both $ and window.jQuery in order to support the jQuery.noConflict() function, etc...

http://api.jquery.com/jQuery.noConflict/

$ is used because it is convenient, but this comes at the price that it may be used by more than one library.

Does that help?

Answer

Javascript doesn't have the means of providing the kind of protection you are looking for.

JQuery isn't "protecting" those variables. It's just copying the references $ and jquery into two other variables. The code you have read is equivalent to:

var obj1 = {}; /* create an empty object and reference it as obj1 */
var obj2 = obj1; /* made a second reference to that same object */

This code doesn't "protect" obj1. It's perfectly valid that your code later on changes the value of obj1:

obj1 = 'foo'; /* now obj1 references a string */

obj1 doesn't "magically retain its value"; after that line, it's just a string. But the object is still available in obj2.

Answer

The purpose of those lines is to be able to restore the original $ and jQuery global variables in case jQuery itself overrides them. It doesn't do anything to protect other code from overriding jQuery.

If you want to protect your own namespace, you can do a setInterval that checks if the global variable is still an instanceof your object (only if your object is protected inside a closure, otherwise it can be modified too). But, this isn't good practice, as the idea of javascript is to be able to extend and customize. Put the control in the hands of the developer, don't try and "lock in" your objects.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.