i really tried to understand, what meaning the the following contruct has in JS, but i could not figure out:
how it works
why & in which situation this construct should be used?
Pls could someone can tell me? Thank you!
(function () {
...
}());
// Or in jQuery plugins i saw it very often
(function( $ ){
...
})( jQuery );
(function () {
...
}());
Defines a function. Calls it immediately. Doesn't store it anywhere.
Usually used to limit the scope of variables inside it.
(function( $ ){
...
})( jQuery );
Exactly the same, except it has an argument. Used so the unhelpfully non-descriptive variable $ can be used without having namespace conflicts with all the other libraries that thought $ was a good name for a variable.
This is called Closure and it's main point is to encapsulate your inner code in order not to mix it with a global scope.
Read this for more details
The second part
(function( $ ){
...
})( jQuery );
Is used to enable your code to use $ as a reference to the jQuery object, without it conflicting with other javascript libraries (like Prototype).
See the jQuery documentation:
http://docs.jquery.com/Using_jQuery_with_Other_Libraries#Referencing_Magic_-_Shortcuts_for_jQuery
These are closures. There is tons of information on this style of JavaScript programming but the gist of it is that its an immediately executing function. If you look closely at the syntax this makes perfect sense -
( ) causes an execution to take place.
//Function immediately executes.
(function() {
});
//Wait we can do better, let's pass in an argument
(function($) {
//$ is now a local variable inside this tightly scoped function
//So that I can describe this as a closure I've added members to this function
var foo = 0,
bar = function() {
return foo;
};
return {
foo: bar
};
}(jQuery));
Related
I'm not sure which JavaScript design pattern I'm following. Can someone please help shed some light on it?
var masonrySupport = ({
large__videos__support: function() {
$('.masonry-container .largeRec').find('.itemMasVideo').parent().addClass('item_largeRec_video_height');
},
smallRec__videos__support: function() {
$('.masonry-container .smallRec').find('.itemMasVideo').parent().addClass('item_smallRec_video_height');
},
init: function() {
this.large__videos__support(),
this.smallRec__videos__support()
}
})
masonrySupport.init();
There are two "patterns" I can see here.
Using self invoking closure to isolate scope.
(function($) {
// Code here
})(jQuery);
Helps mitigate the creation of accidental global variables.
(Kind) the module pattern, where you create an object with a bunch of methods on it, and call init(). I prefer to self invoking closure version of it. The Revealing Module Pattern.
The pattern you are using is called the Module Pattern, and it is one of the most important patterns in JavaScript. You outer wrapper creates an anonymous scope that provides privacy and state to the code that you place inside it.
(function($) {
// Everything in here is private and stateful
// and we can access jQuery through the imported $ variable
})(jQuery);
To your scope, you're also passing the global jQuery object. This method is called global import, and is faster and clearer than accessing the implied global from within your scope.
Inside your scope, you are creating an API that is accessible through the masonrySupport variable, making it a Revealing Module Pattern.
I don't see this as a design pattern in the strict sense of terminology. May be associated with the module pattern, but it needs to return something to be accessible outside of it's inner scope. It's only a self executing function invoked inside a scope which in this case is jQuery. This is used in many jquery plugins. You isolate the scope of the self executing function to a specific - lets say - domain.
This can be found on the first declaration:
(function($) {
...
})(jQuery);
By closuring the function you are guarding the functions and variables declared inside the scope to a specific domain, in this way eliminating the possibility to accidentally override or redeclare some function or variable declared in the global scope. It's a common practice to isolate the scope from the global object which in Javascript world is the Object or on DOM context is window.
And it continues with the self executing function:
$(function() {
...
})
Effectively what is being done here is, once the document loads, execute two functions - 'large__videos__support' and 'smallRec__videos__support.'
Let's understand how it is being achieved,
Firstly it is Immediately-Invoked Function Expression (IIFE) in action. This pattern is often used when trying to avoid polluting the global namespace, because all the variables used in the function are not visible outside its scope.
(function($) {
...
})(jQuery);
Short hand of $( document ).ready() is being used. More here.
$(function() {
...
});
Thirdly, you are initializing one object being referenced by 'masonrySupport' and calling its method 'init.'
In JS, this is called and Immediately Invoked Function Expression (IIFE), and is known as the module pattern.
However in jQuery this pattern is used to create jQuery Plugins. I advise you to follow the best practices to make it work.
Check that jsfiddle to get you started.
Below the JS part:
(function( $ ) {
$.fn.masonrySupport = function( option ) {
if ( option === "large") {
this.find('div.itemMasVideo').parent().addClass('item_largeRec_video_height');
}
if ( option === "small" ) {
this.find('div.itemMasVideo').parent().addClass('item_smallRec_video_height');
}
return this;
};
}( jQuery ));
$( 'div.masonry-container.largeRec' ).masonrySupport( "large" );
I'm trying to build a Javascript library that will provide some functionality for a JQuery Plugin I'm putting together.
I got the following skeleton code from searching online although I'm not quite sure how it all works (I do know it's a closure). I've added my functions via declarations.
(function(window, document, $) {
function func_1(){
return 1;
}
function func_2(){
return 2;
}
})(window, document, jQuery);
So I put the above code in a separate JS file and then source it in my HTML page, then I run try to run the function like so (Note: I have JQuery set up as well):
<script type="text/javascript">
$(document).ready(function() {
console.log(func_1());
});
</script>
However, I seem to be getting some errors in Firebug (ReferenceError: func_1 is not defined).
I have two questions:
How do I call my functions?!
I'd like to be able to call the functions in the following format: className.functionName(). How do I restructure the skeleton code to enable me do this and, say, call my function like this: Device.func_1()?
Thanks for your anticipated assistance.
The closure is used to hide internal functions from the rest of the code. You need to explicitly expose the public functions of the library:
var Device = (function(window, document, $) {
function func_1(){
return 1;
}
function func_2(){
return 2;
}
var internalDevice = {
func_1: func_1,
func_2: func_2
};
return internalDevice; // expose functionality to the rest of the code
})(window, document, jQuery);
The (function(window, document, $) {})(window, document, jQuery); part is called an immediately invoked function expression (IIFE). It's used to avoid leaking all the library functions into the global scope. Otherwise, if some other library had a func_1 function it would either be overwritten or overwrite your library's func_1.
The arguments to the function are used to control how the library can affect other parts of the code and relies on it. For example, someone might overwrite the window.$ library so that $ is no longer available everywhere in the code. But since you have a local reference in the closure you can still access it.
Alternatively to using the code above - returning an object - you could also assign your library directly to the global scope:
(function(window, document, $) {
...
window.Device = internalDevice; // expose functionality to the rest of the code
})(window, document, jQuery);
I can only answer question number two, but you can create that by doing this:
var Device = {
function func_1()
{
// your first function
},
function func_2()
{
// your second function
}
};
That way you can just call:
Device.func_1();
Hop that helps :)
When something is inside a closure the scope of it is changed to that closure. func_1 and func_2 can only be seen inside the anonymous function calling them and below.
I am working on a web project that has a large amount of javascript and we started hitting namespace collisions because we were adding everything to "$.".
I read up about namespacing and found the great article at http://addyosmani.com/blog/essential-js-namespacing/
I tried to set up the namespace inside of an IIFE as recommended and thought I was in luck because the function was already setup as
(function() { ... });
so I converted it to:
(function(namespace, undefined) { ... })(window.stuff = window.stuff || {});
only to find (after hours of work) that actually the original was
$(function() { ... }
Which means it was all being called in jQuery's ready() function.
I would like to keep the namespacing IIFE but cannot figure out how I would use it within jQuery's ready() function. Is this possible and if so how?
var namespace = (function() {
// local variables and functions
function readyHandler($) {
// DOM ready code
$("selector").method();
}
// exposed methods
return {
readyHandler: readyHandler
};
})();
jQuery(namespace.readyHandler);
Mmm, not sure if you got the concepts straight... None of those functions looks like an Immediately Invoked Function Expression because you're not invoking the function.
(function() { ... } ());
--^-- invoke function
jQuery's ready already creates a new closure so you don't need an IIFE anyway.
In any case, when using jQuery you can namespace your plugin in the $ namespace with an object that way you don't pollute it.
$.myplugin = {
...
}
I am studying Backbone and the todo example apps from http://todomvc.com/
I have noticed there are 3 severals ways of starting the code in the files:
$(function() {
// code here
});
$(function( $ ) {
// code here
});
(function() {
// code here
}());
I do not understand the differences and when I should use one over the other.
I also saw some people using this to start their code:
$(document).ready(function(){
// code here
});
From what I have seen, this is the full way of writing it right?
In a more general way, should I always include my javascript code into something like that in each files?
Thanks for your advice.
$(document).ready(function(){}) ensures that your code runs on DOM ready, so that you have access to the DOM. You can read more about this in jQuery's documentation.
$(function(){}) is just an alias to #1. Any code in here will wait for DOM ready (see the docs).
$(function($){}) is equivalent to #1 and #2, only you get a clean reference to jQuery in the local scope (see the note below). You can likewise pass in $ to the function in #1, and it'll do the same thing (create a local reference to jQuery).
(function(){}()) is just a self-executing-anonymous-function, used to create a new closure.
Please note that none of these are specific to Backbone. The first 3 are specific to jQuery, while #4 is just vanilla JavaScript.
Note: To understand what's going on in #3 above, remember that $ is an alias to jQuery. However, jQuery is not the only library that uses the $ variable. Since the $ might be overwritten by someone else, you want to ensure that within your scope, $ will always reference jQuery - hence the $ argument.
In the end, it basically boils down to the following 2 options:
If your JavaScript is loaded in the head, you have to wait for document ready, so use this:
jQuery(function($) {
// Your code goes here.
// Use the $ in peace...
});
If you load your JavaScript at the bottom of your document (before the closing body tag - which you should definitely be doing), then there's no need to wait for document ready (since the DOM is already constructed by the time the parser gets to your script), and a SEAF (A.K.A. IIFE) will suffice:
(function($) {
// Use the $ in peace...
}(jQuery));
P.S. For a good understanding of Closures and Scope, see JS101: A Brief Lesson on Scope.
I guess it makes sense to start out, by realizing that $ = jQuery. The purpose of which down below when reading about namespaces within anonymous functions will make more sense. But in essence, you can use either of them. One would use jQuery() instead of $() if they were using multiple libraries, and wanted the $ to be used by the other one.
$(document).ready(function(){
// Here we have jQuery(document) firing off the ready event
// which executes once the DOM has been created in
// order to ensure that elements you are trying to manipulate exist.
});
$(function () {
// Short-hand version of $(document).ready(function () { });
});
More information on Document.ready()
Putting the $ within the parenthesis ensures the jQuery $ alias (you can be safe it always signifies jQuery this way).
$(function ($) { /* code here : $ always means jQuery now */ });
Lastly you have an IIFE (Immidiately-Invoked Function Expression)
- IIFE explanation
(function (myNameSpace, $) {
// This is an anonymous function - it is ran instantly
// Usually used for namespaces / etc
// This creates a scope/wrapper/closure around everything inside of it
}(window.myNameSpace, jQuery));
The $ at the top (with it's matching jQuery on the bottom) signify that the
$ (dollar sign) stands for jQuery within the scope of the namepsace.
This is done to ensure that other libraries do not collide with what the developer
intends/wants the $ to be used with.
(function (myNameSpace, $) {
// Now because of all of this scope/wrapper/closure awesome...
// you can create -INTERNAL- variables (sort of like Private variables from other langs)
// this variable cannot be accessed outside the namespace unless it is returned / exposed
var internalVariable = '123'; // Internal
// Even Internal functions!
function privateFunction () {
console.log('this is private!');
}
// --------------------------------------------------------
// Public -method- of nameSpace exposing a private variable
// Notice we're using the myNameSpace object we exposed at the top/bottom
myNameSpace.nameSpaceMethod = function () {
privateFunction(); // we can call the private function only inside of the namespace
return internalVariable; // now we could get this variable
};
}(window.myNameSpace, jQuery)); // notice these mirror the above arguments in the anon function
More information on anonymous functions
Now if we're outside of the namespace, we can see how these internal/public methods and variables are effected:
// This will come up undefined
alert(internalVariable);
// This will trigger a -method- of the myNameSpace namespace - and alert "123"
// Showcasing how we access a Public method - which itself has access to the internal variable
// and exposes it to us!
alert(myNameSpace.nameSpaceMethod());
These two:
$(function() {
// code here
});
$(document).ready(function(){
// code here
});
Are directly equivalent, they are both the way to start some jQuery when the document has loaded. The former is just a shorter version of the latter.
This one:
(function() {
// code here
}());
is just a scoped function with zero parameters, which is immediately called with zero parameters.
Long story short, I have a long code that uses jQuery. Lots of files, functions, etc. A less than ideal amount of our users are having issues with our code because some addons, toolbars and the like they have installed breaks our JavaScript code because of jQuery gets included twice and nasty stuff like that.
I thought I could just
Include jQuery
Use $.noConflict
Then include the whole rest of my code between something like:
.
(function($) {
// All of my code goes here.
})(jQuery);
I haven't checked if this fixes our issues with those users, but it does work. The problem is, in one part of the site (image upload) we have an iframe that needs to call some of those functions defined in our big chunk of code. I've tried putting those functions out of this unnamed function call, but it uses, on itself, other functions which have to be there.
Any idea or workaround of how could I be able to access functions defined inside that function (shown above) from a code that's outside of it?
Thanks!
You cannot access a function context from the "outside world". Well, to be accorate you could do it in some older js engines which allowed for accessing .__parent__ attributes, but that is old'n'busted and no longer available.
However, you would need to either expose some functions within your closure, or you creating a namespace object where you write all of your logic in (which also has to be available in the parent context).
So I'd suggest something like
(function( $ ) {
function myFunc() {
// do stuff
}
function anotherFunc() {
}
window.myFunc = myFunc; // expose myFunc globally
}( jQuery ));
Maybe even better:
var myNameSpace = { };
(function( $ ) {
myNameSpace.myFunc = function() {
// do stuff
};
}( jQuery ));
// somewhere else
myNameSpace.myFunc();
It is not an ideal practice, but you can declare those functions in the global scope.
(function($) {
globalFunct = function (arg1, arg2) { // Don't use var keyword
...
};
})(jQuery);
It isn't ideal because you can run into naming collisions, much like you are observing with jQuery. Improve upon this approach by putting all of your globally-accessible methods in a "package." Choose a unique name for it. This will prevent collisions.
// Somewhere outside of your anonymous function, in the global scope
var myPackage = {};
(function($) {
myPackage.globalFunct = function (arg1, arg2) {
...
};
})(jQuery);
Then call that method by invoking myPackage.globalFunct().
Why are you wrapping your code in a call to the jQuery function object which you pass in to your self-executing anonymous function; are you meaning to create a jQuery object from all of your code?
In order to expose your code to the outside world, you need to assign your functions and objects to an object which is outside of the scope of your code, such as the window object.
For example, if you had created an object containing various methods and properties that you wanted to expose, you could do this:
//Your self-executing anonymous function
(function($)
{
//Object which contains various useful methods and properties
var useful = {...};
//Expose it to the outside world
window.Useful = useful;
})(jQuery);
EDIT: as others have noted, it is not an ideal solution as you will indeed run into naming collisions if you are not careful. Also, using an object external to your anonymous function as a namespacing object (as others have stated) is my preferred method
Yes, you can "export" the function from within a closure:
Yes, you can "export" the function from within a closure:
(function() {
function a() {
console.log("a");
}
function b() {
a();
console.log("b");
}
// make b globally available
window.b = b;
})();
b();
window.PARTY_CATS_jQuery = jQuery.noConflict(true);
(function($) {
$(function() {
// All of my code goes here.
});
})(COMPANY_NAME_jQuery);
Then just use PARTY_CATS_jQuery in your global functions
If you feel PARTY_CATS_ is not a unique enough name pick something safer like BABY_KILLER_jQuery