I've the following javascript code
var globalConfiguration = null;
function loadFile(filePath) {
}
function onLoadPage() {
}
function getConfiguration() {
}
function process() {
}
I want to use IIFE to encolose all my functions in a closure to avoid cluttering the global name space,so I wrote :
(function(window){
var globalConfiguration = null;
function loadFile(filePath) {
}
function onLoadPage() {
}
function getConfiguration() {
}
function process() {
}
});
However, I do not understand this notion very well, now in my HTML page how would I call my function onLoadPage?
You can't without putting it in the global namespace somehow.
My recommendation to structure code like this:
function ExampleHelper() {
(function(scope) {
scope.globalConfiguration = null;
scope.loadFile = function(filePath) {
};
scope.onLoadPage = function() {
};
scope.getConfiguration = function() {
};
scope.process = function() {
};
})(this);
}
var foo = new ExampleHelper(); // "foo" now contains all of your functions
foo.onLoadPage();
Now that you have enclosed the module, you need to decide what you want to expose to the outside world. Anything you want to expose, you can export. Also, you need to decide what context (in this case, window) that you want to attach to. Then pass the context in right away (thus completing the IIFE).
For example:
(function(window){
var exports = {};
var globalConfiguration = null;
function loadFile(filePath) {
}
function onLoadPage() {
}
function getConfiguration() {
}
function process() {
}
exports.getConfiguration = getConfiguration;
window.myModule = exports;
})(window);
Attaching to the passed in window object is one way to export things out in a controlled fashion. So, you do need to pass the context (in this case window) to the IIFE. Perhaps, window will not always be the context for the call.
After running this code, myModule will be available on the global scope.
You can set your function to window.onload callback.
(function(window) {
var globalConfiguration = null;
window.onload = onLoadPage;
function loadFile(filePath) {}
function onLoadPage() {
alert('hello world');
}
function getConfiguration() {}
function process() {}
}(window));
This is called chaining of functions/methods and is usually done for better readability of the code and to avoid the usage of temporary variables to hold the return value of each function.
Check this post on chaining methods which helped me to understand the chaining better.
I see you wanted to use closures to avoid cluttering the global object. However, do note that we write functions for reusability. Though you create a closure, ensure that your methods inside the outer function are abstracted such that they can be used by other parts of the code.
For ex: from your code, you have a loadFile method which could be reused.
Now to see how you can use the methods you described in a chain.
Assumptions: (since i don't know why you wrote those methods, i am making some assumptions).
loadFile(filepath) - returns a file object
onPageLoad() - once the page is loaded, it returns the object or id of the input file
getConfiguration() - gets the file path
process() - process the file
onPageLoad().loadFile(getConfiguration()).process();
The important part is that the scope of the object is set correctly in the chaining. In order to do this, each method must return the reference to appropriate object.
Hope this helps.
Related
I have seen javascript something like this
var Gallery = function () {
var helloworld1 = function () {
alert('hey1');
}
var helloworld2 = function () {
alert('hey2');
}
var helloworld3 = function () {
alert('hey3');
}
}();
How would I call the helloworlds within this javascript file?
I've tried
helloworld1();
Gallery.helloworld1();
Gallery().helloworld1();
But they don't seem to work.
Also, are there any reasons why I should be writing my javascript in the above manner, rather than just using
function helloworld() {
alert('hey1');
}
Perhaps you want
var Gallery = {
helloworld1: function () {
alert('hey1');
},
helloworld2: function () {
alert('hey2');
},
helloworld3: function () {
alert('hey3');
}
};
Gallery.helloworld2();
or
var Gallery = function () {
this.helloworld1 = function () {
alert('hey1');
}
this.helloworld2 = function () {
alert('hey2');
}
this.helloworld3 = function () {
alert('hey3');
}
};
new Gallery().helloworld2();
Also, are there any reasons why I should be writing my javascript in the above manner?
It namespaces the functions. Everything to do with galleries is in the Gallery object.
Symbols declared in a function are only visible within that function (and inside other functions defined within it. That goes for symbols declared with var and function equally. Thus, in your first example, you cannot access those functions from outside the outer function.
Functions can be "exported" by having the outer container function return an object, with the functions as property values.
As to whether functions should be declared with function or var, it's a matter of personal style. I (personally) like function, but I know of many seriously talented JavaScript programmers who use var initializations.
About your 1st Question. What actually is happening that the variable Gallery is being assigned the value that your function is returning, which is basically undefined.
You are not able to do Gallery.helloworld() because .. Gallery is undefined.
The helloworld1() is not working as it would look for a helloworld1 function on the global object which is not defined again.
This is because you defined these functions inside the function scope.
You need to do this to achieve what you are trying to do.
var Gallery = function(){
return {
helloworld1:function(){alert('hey1')},
helloworld2:function(){alert('hey2')},
helloworld3:function(){alert('hey3')}
}
}();
This assigns Gallery to an object that has all the three functions as its properties. In this way then you can call. Gallery.helloworld1() which would print the alert.
This is a way of protecting an object from further modifications.
E.g you could do this
var Gallery = function(){
var realGallery = {no_of_pictures:1};
return {
getNumberOfPictures:function(){return realGallery.no_of_pictures;},
increasePictures:function(){realGallery.no_of_pictures += 1;},
decreasePictures:function(){realGallery.no_of_pictures -= 1;}
}
}();
This way no one can directly set no_of_pictures on realGallery object. They can only be incremented or decremented.
About your 2nd Question. It is generally not considered a good practice to use globals as anyone can tamper with them.
Lets say you defined function helloworld() {alert('hey1');}
Someone could easily redefine helloworld like this.
function helloworld(){alert('go away right now !!');}
So someone could easily completely break down your application with some small hack. That's why globals are considered a bad practice in javascript.
If you notice in the code that you cited, the parentheses after the Gallery function. Those are there to call the function immediately. So as soon as the code runs, that function is called. And that particular function is assigning the 3 hello world functions to their respective variables. But there is no access to those functions because o the reasons the first answer stated. So I'm not sure of the purpose of that code.
The key here is you have a self executing function, which doesn't return a value, therefore you can't access anything from within it, regardless of whether it was declared using var or this.
The goal of this coding style is to avoid polluting the global space with lots of variables and functions. Everything is encapsulated into the Gallery function. Using this style, you wouldn't try to access anything from the outside. It is like a bootstrap function where a set of procedures are executed and then it finishes, without the need to call anything inside again.
If you want to access from the outside, you need to first remove the self executing part, and secondly declare public properties or public pointers to the private properties:
var Gallery = function () {
var helloworld1 = function () {
alert('hey1');
}
var helloworld2 = function () {
alert('hey2');
}
var helloworld3 = function () {
alert('hey3');
}
this.helloworld1 = helloworld1;
this.helloworld2 = helloworld2;
this.helloworld3 = helloworld3;
};
var g = new Gallery();
g.helloworld1();
If you were to have the function return itself, then you can access the inside (providing the methods/properties are made public with this:
var Gallery = function () {
this.helloworld1 = function () {
alert('hey1');
}
return this;
}();
console.log(Gallery.helloworld2);
En example can be found in Twitter'a typeahead.js here:
function () {
// ...
return this.each(initialize);
function initialize() {
// ...
}
}
Questions:
What are the scopes and what function sees what?
What is the reason for using such a construct (usage scenarios and advantages)?
Javascript has function based scope, which means that every thing defined inside a function is available from the first line, since the definition is "hoisted" by the complier.
That goes for both variable and function definitions - variable values however, are not available until after assignment.
You can read all about javascript scoping and hoisting here
This means that the function initialize is available from the first line of the wrapping anonymous function.
There is no real reason, and no advantages, for doing it that way, unless you count the code structure as an advantage.
Personally I don't see any reason to do this. For me even it looks a little bit weird. Martin is right. You should be careful, because the defined variables are not accessible like functions. For example this doesn't work:
var getValue = function(func) {
return func();
}
var f = function() {
return getValue(now);
var now = function() {
return 10;
}
}
alert(f());
However, this works:
var getValue = function(func) {
return func();
}
var f = function() {
return getValue(now);
function now() {
return 10;
}
}
alert(f());
In the module pattern in JavaScript "Immediately-Invoked Function Expressions" (also known as self-executing anonymous functions) are used as self executing functions that return an object.
How can a self-executing function hide private variables and only expose the returned object. Why does this not happen with a normal JavaScript function?
So in the following mini module, why could we not achieve the same concept of encapsulation without the enclosing ()()?
var Module = (function () {
var privateVariable = "foo",
privateMethod = function () {
alert('private method');
};
return {
PublicMethod: function () {
alert(privateVariable);
privateMethod();
}
};
})();
How can a self-executing function hide private variables and only expose the returned object. Why does this not happen with a normal JavaScript function?
It does happen with normal JavaScript functions.
function MakeModule() {
var privateVariable = "foo",
privateMethod = function () {
alert('private method');
};
return {
PublicMethod: function () {
alert(privateVariable);
privateMethod();
}
};
}
var Module = MakeModule();
would work just fine.
The only difference is that the anonymous function introduces one less global variable and allows for itself to be garbage collected while MakeModule can't be collected unless explicitly deleted by the author.
The privateness is because of closures. The "var privateVariable" is closed over by "PublicMethod", so only that function can access the variable because only it has it in its closure. It cannot be referenced by anything else and is "private"
This happens not only in "Immediately-Invoked Function Expressions" but also in normal function calls. It is just a way to immediately create the closure when defining the module instead of doing it later when you call the outer function.
Also see this post from Douglas Crockford himself: http://javascript.crockford.com/private.html
You can define a anonymous function via named function.
Example:
//factorial
(function(n){
var self = function(n){
//call self
return n > 0 ? (self(n-1) * n) : 1;
}
return self;
})()
Is there any way to refer to the function object that you're currently executing in? If it's not a method of any object or not called with .call() or .apply(), the this pointer is likely just window, not the function object.
I often use a design pattern like this for global variables that I want scoped to a particular function as this keeps them out of the top level namespace:
function generateRandom() {
if (!generateRandom.prevNums) {
generateRandom.prevNums = {}; // generateRandom.prevNums is a global variable
}
var random;
do {
random = Math.floor((Math.random() * (99999999 - 10000000 + 1)) + 10000000);
} while (generateRandom.prevNums[random])
generateRandom.prevNums[random] = true;
return(random.toString());
}
But, I'd rather not have to spell out the function name every time I want to use a variable scoped to that object. If the name of the function ever changes, there are then a lot of places to change the name.
Is there any way to get the currently executing function object?
Well, you could use arguments.callee()...
https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee
From MDN:
Description
callee is a property of the arguments object. It can be used to refer
to the currently executing function inside the function body of that
function. This is for example useful when you don't know the name of
this function, which is for example the case with anonymous functions.
Note: You should avoid using arguments.callee() and just give every
function (expression) a name.
BUT...
What you really want are Javascript Prototypes.
function RandomSomethingGenerator()
{
this.prevNums = {};
}
RandomSomethingGenerator.prototype.generate = function() {
var random;
do {
random = Math.floor((Math.random() * (99999999 - 10000000 + 1)) + 10000000);
} while (this.prevNums[random])
this.prevNums[random] = true;
return(random.toString());
};
Why do I say this?
1.) You're dirtying the global space with all those functions.
2.) Even if you like Jani's suggestion, and you want a "static" function like you have now, my suggestion would be the same, but with a twist: Create your global function, and wrap an instance of an object (built from a prototype) inside the closure and make the call to it (so, basically, make yourself a singleton).
As in this (adapted from Jani's answer):
var randomSomething = (function() {
var randomSomethingGenerator = new RandomSomethingGenerator();
return function() {
randomSomethingGenerator.generate();
};
})();
I don't think there's any way to do exactly what you ask, but you could use a closure for your function-local static variables instead.
You can easily achieve this using an IIFE:
var generateRandom = (function() {
//any function's static variables go here
var prevNums = {};
return function() {
//function code goes here
var random;
do {
random = Math....
}
prevNums[random] = true;
return random.toString();
};
})();
You want arguments.callee. From MDN - callee:
callee is a property of the arguments object. It can be used to refer to the currently executing function inside the function body of that function. This is for example useful when you don't know the name of this function, which is for example the case with anonymous functions.
For example:
> foo = function() { console.log(arguments.callee); };
> bar = function() { foo() };
> bar();
function () { console.log(arguments.callee) }
However, I think this is being deprecated. The above link says, "The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode."
How can i call a YUI function that is wrapped inside a YUI().use from javascript?
example
Below is a YUI function "runShowAnim" which executes animShow.run(); for an animation effect...
var runShowAnim = function(e) {
animShow.run();
};
I want this effect to happen when i validate something in a javascript function. I tried to call it as below. But it doesn't seem to work.
function notifyUser(message) {
document.getElementById("msgArea").innerHTML = message;
runShowAnim();
}
I achieved this by sandwiching the YUI function completely inside a function and calling that function..
var runShowAnim = function() {
YUI().use('anim', 'node', function(Y) {
var animShow = new Y.Anim({
node: '#msgArea',
to: { height: 50,opacity:1 }
});
animShow.run();
});
};
now i can call runShowAnim without any problem like in the below sample function..
function notifyUser(message) {
document.getElementById("msgArea").innerHTML = message;
runShowAnim();
}
If you want to call a function, you have to suffix the function name with () and include 0 or more comma separated arguments between them.
runShowAnim();
If the function doesn't have global scope (as yours will have if it is declared inside a function passed to use()) and not passed outside in some way then you can only do this from the same scope.
I think you're missing the parentheses.
function notifyUser(message) {
document.getElementById("msgArea").innerHTML = message;
runShowAnim(); // right here
}
YUI.thefunction()?
I think you need to call it with namespace too
something similar to
var X = function(){};
X.Y = function(){};
X.Y.Z = function(){};
X.Y.Z.foo = function(e){alert(e);}
//foo("me");<-error
X.Y.Z.foo("me");
If you want to call a function that has been defined inside the closure (the function passed as the last parameter to YUI.use) from outside it, you need to expose the function globally.
Either define a global variable outside the closure and assign your function to it, or assign your function to the window object
i.e.
var runShowAnim;
YUI().use(function(e){
runShowAnim = function(){alert('called');}
});
runShowAnim();