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?
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.
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).
});
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?
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.
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.
Related
https://github.com/placemarker/jQuery-MD5
Requirements
None.
If jQuery is not available, the md5 function will be added to the global object
what does this mean?does md5.js need jquery or not?
No, it doesn't.
jQuery is an optional integration which allows you to compute the MD5 hash via the jQuery $ variable, like so:
var md5 = $.md5('value');
Because it's optional, when not present you will still be able to compute the hash, in the following way:
var md5 = md5('value');
You can infer that from the source code, which exports the function to the given scope. The scope is defined here:
// ...
}(typeof jQuery === 'function' ? jQuery : this));
If the jQuery is not defined as a function, the global this object will be used. This also means that the code will export the MD5 function to either jQuery or global scope but not both, which is likely why this answer has been down-voted.
In Javascript, it's possible to have some kind of inheritance, by using function contructors and their "prototype" attribute (i.e the "parent of future instances"), or more recently Object.create(), to get new objects.
However recently I needed to "override" the Jquery object ("$") for one of my projects, that is to say, provide a similar function, which also has all the fn/extend/... [inherited] attributes of the original "jQuery" factory function.
The goal was to have a "$()" function which always received "window.parent" as the second parameter by default, so that the whole program modified the parent frame and not the iframe in which the program was loaded.
Typically I expected to be able to do something like this:
var oldJQ = $;
$ = function (selector) {
return oldJQ(selector, window.parent);
}
$.__proto__ = oldJQ .__proto__;
$.extend({...}); // must work
Despite numerous attempts, I couldn't get it to work, I always got simple objects instead of real functions when using the "new" keyword, or the inheritance didn't work. I found alternative ways (for example, by copy-pasting all attributes from $ into my new function object), but it seems to me like a horrible way of doing stuffs.
Is there any way to have a new function object which has, as a parent/prototype, the original $ object ?
While functions are objects in javascript, they aren't regular objects. Specifically, they're objects for which inheritance is broken. Functions are not the only such objects in the language, DOM elements are similarly handicapped. That's one reason jQuery is implemented as wrapper around DOM rather than extending the DOM's features via inheritance.
Fortunately, while OOP doesn't work in this case, we can take inspiration from jQuery itself and use FP to do what we need. In other words, while you can't inherit functions, you can wrap it in another function.
For example, if you need a special console.log function for your app that sends logs back to your server you can override it by redefining it:
var log_orig = console.log;
console.log = function () {
ajaxlog([].slice.call(arguments,0).map(function(x){
return JSON.parse(x);
}).join(',');
log_orig.apply(console,arguments);
}
Or if you want a special version of $ that does something extra:
function $$ () {
/*
* do extra stuff
*/
return $.apply(null,arguments);
}
Or if you want to override $ instead if wrapping:
var old$ = $;
function $ () {
/*
* do extra stuff
*/
return old$.apply(null,arguments);
}
Let's assume that we have following jQuery plugins (each of them in separate files):
$.fn.foo
$.fn.foo.bar
$.fn.foo.baz
I use standard jQuery plugin pattern. The first one is actually a proxy or "facade" to the rest plugins of it's namespace.
For example, when I call $('#el').foo(), under the hood I also call:
var context = this; // context is equal to $('#el')
$(context).foo['bar'].apply(context);
$(context).foo['baz'].apply(context);
There are two problem when I want to call only (without $.fn.foo) $('#el').foo.bar(). The first problem is that there are no $.fn.foo namespace but I can create it, so this is actually no problem. The second problem is that this inside $.fn.foo.bar is equal to document object but I want to be equal to $('#el'). How can I do that?
So, making a long story short, both should work:
$('#el').foo(); // This also calls foo.bar and foo.baz under the hood
$('#el').foo.bar(); // I'm calling foo.bar explicitly
I think you might just need to follow a different plugin pattern. Here is a nice repository of jQuery plugin patterns, but the one you might want to look at would be the namespace pattern - you'll see how the namespace gets defined initially if it doesn't already exist, and this allows you to more easily extend from a single namespace across multiple scripts.
Update: Hmm, I'm still learning so I wouldn't say I'm an expert at this, but trying to get this $('#el').aaa.bbb.ccc() to work got really messy for me. Maybe it would be better to not use that format, but instead do this (demo):
$.aaa.bbb.ccc( $("#el") );
because then it is relatively easy to set up:
(function() {
if (!$.aaa) {
$.aaa = {
bbb : {
ccc: function(el, options){
alert(el[0].id);
}
}
};
};
})(jQuery);
$(function() {
$.aaa.bbb.ccc( $("#el") ); // alerts "el"
});
I was looking over the JavaScript source code for SlickGrid.
I've noticed that slick.grid.js has the following structure:
(function($) {
// Slick.Grid
$.extend(true, window, {
Slick: {
Grid: SlickGrid
}
});
var scrollbarDimensions; // shared across all grids on this page
////////////////////////////////////////////////////////////////////////////
// SlickGrid class implementation (available as Slick.Grid)
/**
* #param {Node} container Container node to create the grid in.
* #param {Array,Object} data An array of objects for databinding.
* #param {Array} columns An array of column definitions.
* #param {Object} options Grid options.
**/
function SlickGrid(container,data,columns,options) {
/// <summary>
/// Create and manage virtual grid in the specified $container,
/// connecting it to the specified data source. Data is presented
/// as a grid with the specified columns and data.length rows.
/// Options alter behaviour of the grid.
/// </summary>
// settings
var defaults = {
...
};
...
// private
var $container;
...
////////////////////////////////////////////////////////////////////////
// Initialization
function init() {
/// <summary>
/// Initialize 'this' (self) instance of a SlickGrid.
/// This function is called by the constructor.
/// </summary>
$container = $(container);
...
}
////////////////////////////////////////////////////////////////////////
// Private & Public Functions, Getters/Setters, Interactivity, etc.
function measureScrollbar() {
...
}
////////////////////////////////////////////////////////////////////////
// Public API
$.extend(this, {
"slickGridVersion": "2.0a1",
// Events
"onScroll": new Slick.Event(),
...
// Methods
"registerPlugin": registerPlugin,
...
});
init();
}
}(jQuery));
Some code has been omitted for brevity and clarity, but this should give you the general idea.
What is the purpose of the the following: (function($) { // code }(jQuery)); Is this the module pattern that I've seen talked about? Is this meant to keep the global namespace clean?
What do the $.extend() lines mean?: The top $.extend(true, window, { // code }); looks like it has to do with a "namespace"; what's a namespace? It looks like the bottom $.extend(this, { // code }); is used to exposed 'public' members and functions? How would you define a private function or variable?
How would you initialize multiple "SlickGrids" if you wanted to? How much would they share and how would they interact? Note the "constructor" function: function SlickGrid(...) { // code }.
What are some books, links, and other resources on coding in this style? Who invented it?
Thanks! ♥
This is a jQuery plugin.
(function($) { // code }(jQuery)); gives you a new function scope so your names are not dumped into the global scope. Passing jQuery as $ lets you use the $ shorthand even if other Javascript libraries use $.
$.extend is a jQuery method to copy properties from one object to another. The first argument true means it should be a deep rather than a shallow copy. By extending window, new global properties are created, in this case, Slick.
The $.extend(this,...) at the bottom is in a capitalized function SlickGrid. SlickGrid is meant to be used as a constructor, in which case this will be the newly-created object, so this extend is adding properties to the object. They are effectively public members. In this code sample, measureScrollbar is private: it is only visible to the code defined in this function, not outside it.
You can create a number of grids with:
var grid1 = new Slick.Grid(blah, blah);
var grid2 = new Slick.Grid(blah, blah);
In the code you've shown, the only thing these two instances will share is the scrollBarDimensions variable.
(function($) { // code }(jQuery))
This is a closure. It basically keeps everything inside it "// code" safe from things outside it. You pass in jQuery and the $, but someone with more knowledge will have to explain why that is necessary.
$.extend()
This is a jQuery function that will take two objects and merge them together. Replacing the first object "window" with the second object {Slick: {Grid: SlickGrid}}. This means if there is a window object with Grid:Null it would now equal Grid:SlickGrid.
Adding true as a first parameter means it will replace nested objects as well:
var firstObj = { myObj:{
first:this,
second: {
new: obj
}
}}
$.extend(true, firstObj, {myObj:{second:{new:newer}}});
This is useful if you are using a lot of objects to store information.
Not sure what you mean by #3, but look at http://960.gs for a good grid system.
JavaScript the Good Parts is a great book. Pro JavaScript by John Resig is also a good book to take you beyond the basics.
Simply put, guy in your example just wrote jQuery plug-in of sorts... Check PLUGINS section of jquery.com for more references to sources on how to code plugins. They are simple, straightforward and fun to explore.
For the first question, this construct is a way to allow jQuery to coexist with other libraries which may use the $ function, but still use $ to reference jQuery within a code block.
The entire package is wrapped in a function call with $ as a parameter. The only "main" activity when this is run is to call that function with jQuery as an argument, this giving a reference to the well-known global jQuery to the local parameter $, which masks any global value that $ may have.
1) That function is invoked immediately when the JS file is loaded. It receives the jquery instance as parameter and makes it available internally as "$". All code is encapsulated in that function so (unless you forget a var in front a yet undeclared variable) nothing pollutes the global namespace.
2) All properties of the 2nd object are copied to the 1st object, here "window", which also is the global namespace object in a web browser. Therefore this code does not make much sense. It pretends to encapsulate but does the opposite. Neither does the second invocation of $.extend make all that much sense. It's not wrong, I just think the code "pretends".
4) I very highly recommend you check out the videos from Douglas Crockford at http://developer.yahoo.com/yui/theater/
Crockford is a JS god, very famous (among serious JS programmers) - and in addition great fun to listen to :)
Could someone write down a very simple basic example in javascript to conceptualize (and hopefully make me understand) how the jQuery plugin design pattern is done and how it works?
I'm not interested in how creating plugin for jQuery (so no jQuery code here at all).
I'm interested in a simple explanation (maybe with a bit of Javascript code) to explain how it is done the plugin concept.
Plz do not reply me to go and read jQuery code, I tried, but I it's too complex, otherwise I would have not post a question here.
Thanks!
jQuery has a library of functions stored in an internal object named fn. These are the ones that you can call on every jQuery object.
When you do $("div.someClass") you get a jQuery object containing all <div> elements of that class. Now you can do $("div.someClass").each( someFunction ) to apply someFunction to each of them. This means, that each() is one of the functions stored in fn (a built-in one in this case).
If you extend (add to) the internal fn object, then you automatically make available your custom function to the same syntax. Lets assume you have a function that logs all elements to the console, called log(). You could append this function to $.fn, and then use it as $("div.someClass").log().
Every function appended to the fn object will be called in such a way that inside the function body, the this keyword will point to the jQuery object you've used.
Common practice is to return this at the end of the custom function, so that method chaining does not break: $("div.someClass").log().each( someFunction ).
There are several ways to append functions to the $.fn object, some safer than others. A pretty safe one is to do:
jQuery.fn.extend({
foo: function() {
this.each( function() { console.log(this.tagName); } );
return this;
}
})
Tomalak already posted almost everything You need to know.
There is one last thing that helps jQuery do the trick with the this keyword.
it's amethod called apply()
var somefunction=function(){
alert(this.text);
}
var anObject={text:"hello"};
somefunction.apply(anObject);
//alert "hello" will happen
It really helps in creating abstractions so that framework/plugin users would just use this as intuition tells them, whatever there is inside Your code
It works, as many other js frameworks, using javascript prototype orientation.
For instance you can declare a simple function
var alertHelloWorld = function() {
alert('hello world');
}
And then tie it to an existing object (including DOM nodes)
document.doMyAlert = alertHelloWorld;
If you do this
document.doMyAlert();
The alertHelloWorld function will be executed
You can read more about javascript object prototyping here