JS Encapsulation - IIFE vs Regular Function - javascript

Learning the JS Module Pattern.
I am trying to figure out the differences between an IIFE and a regular function in this use case. It looks like the ONLY advantage of an IIFE is that my module becomes an object (since the IIFE returns immediately) so I don't need to use the call invocation/param () syntax on my module.
Is there any additional benefit? Consider the following code:
//IIFE
var HelloWorldEncapsulated = (function(){
return {
privateMethodEncapsulated: function () {
console.log('ayy lmao encapsulated');
}
}
})();
HelloWorldEncapsulated.privateMethodEncapsulated();
//Just a function
var HelloWorld= function(){
return {
privateMethod: function () {
console.log('ayy lmao');
}
}
};
HelloWorld().privateMethod();
Again, is there any difference between the two besides using () and not using it? It seems that privateMethod is just as hidden in the non-IIFE function as it is in the IIFE. Code here in case you don't want to type 2 words

The only difference in those is when you're executing your function. In your second example, if you want to call another method (or call privateMethod more than once), you'd have to execute it again (not ideal):
HelloWorld().privateMethod();
HelloWorld().privateMethod(); // Calls HelloWorld a second time, creating a
// whole new object to make the call on (bad idea)
...or remember the result of the first execution an dreuse it:
var hw = HelloWorld();
hw.privateMethod();
hw.privateMethod();
...at which point you're back to your first example.

Related

Benefit of Immediately-invoked function expression (IIFE) over a normal function

I'm pretty new to javascript and I read about the module pattern to provide some sort of namespace and have both private and public members, for example:
var module = (function() {
var s = "Hello, i'm private and in closure!";
return {
myString : s,
myFunc: function() { alert(s); }
};
})();
I do see the benefits of that, because it gives you some of the advantages of object-oriented programming. But I've seen a lot of examples of an IIFE that doesn't get assigned to a variable. This (as far as I see) has no advantages at all compared to a normal function that you invoke:
1. IIFE
(function() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
})();
2. Normal function
function Initialize() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
}
Initialize();
They both have private variables that avoid the need of creating global variables and they both execute without returning any value to a variable.
Although the second one gives you the option of choosing a good name that says a lot more than a potential large IIFE without the name, leaving the reader to find out what's happening. The answer I see everywhere is 'to avoid namespace pollution' but both approaches do that, the first one is just a bit harder to understand?
In short:
What is the benefit of using an IIFE over a normal function that I'm missing? Why should I use them?
Sometimes you need to define and call function at the same time and only once so in this case anonymous function helps you. In such situations giving functions a name and then calling them is just excess.
Further sometimes you wants to create a namespace for your variables. So anonymous functions helps you there too. For example
(function($) {
$.fn.pluginName = function(opt) {
// implementation goes here...
}
}(jQuery));
In above case you can safely use $ as jQuery synonym in your code.
If you define a function with name as shown below, then it will create global variable with function name as you defined.
function myFunction() {
// function code goes here.
}
myFunction();
But if you define it without name then it won't create any global variable and your global namespace will not be polluted.
(function myFunction() {
// function code goes here.
}());
Function with names are useful only when you need to call them from different places in your code.

What is the correct way of calling an internal function using the module pattern in Javascript

I am new to Javascript and am still getting my head round the various ways of creating objects i.e constructor+new, prototypal, functional & parts.
I have created what I think is an object factory using the module pattern and want to know what the correct method of calling an internal method would be. Is it via this or function name.
Here is my module:
function chart() {
function my() {
// generate chart here, using `width` and `height`
}
my.sayHi = function(){
console.log('hi');
my.sayBye();
};
my.sayBye = function(){
console.log('Bye');
};
return my;
}
var test = chart();
test.sayHi();
You can see that the first function calls the second using my.sayBye() or is it better to use this.sayBye(). Both produce the same result and run without error.
The module pattern allows you to dispense with the 'this' variable if you want to. I would probably rewrite the above code to look like this and then the question becomes moot.
function chart() {
var hiCount = 0;
function sayHi(){
console.log('hi');
hiCount++;
sayBye();
};
function sayBye(){
console.log('Bye');
};
return {
sayHi : sayHi,
sayBye: sayBye
};
}
var test = chart();
test.sayHi();
In the above code all is defined within the function chart. As JavaScript's scope is at the function level every time the chart function is called a new set of functions will be defined. And a new set of variables can also be defined that are private to the function as they are defined in the function and are not accessible from outside. I added hiCount as an example of how you could do this. The Module pattern allows privacy in JavaScript. It eats more memory than the prototype pattern though as each time a function is declared it is not shared between other instances of the same class. That is the price you have to pay in Javascript to have class variables that are private. I willingly pay it. Removing 'this' from my code makes it easier to understand and less likely that I will fall into problems of misplaced scope.
Using "this" is better approach because you would be able to bind the function directly to the parent function object.And you dont need to return anything from the function.
where as in your case you are explicitly returning another function
Here is the use of "this" approach
function chart() {
this.sayHi = function(){
console.log('hi');
}
}
var test = new chart();
test.sayHi();
Using this approach you would be able to call anything in the prototype of function "chart"
Eg
chart.prototype.hello = function(){
console.log('hello')
}
So you would be able to call the hello function from the same object(test)

How do I make a nonexistent (non-member, non-global) method invocable without using eval?

Let's start from the code:
function say(name) {
var ghost=function () {
function ghost() {
alert('!');
};
return body;
};
eval("var body=''+"+name+';');
eval(name+('=('+ghost).replace('body', body)+')();');
eval(name+'();');
}
function Baal() {
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
say('Baal'); // or just Baal();
Looks like that saying the devil's name invoke his presence (well, maybe he needs somebody for spiritual possession) ..
As you can see the ghost doesn't exist along with Baal, but we can invoke it since there're evals in say(name).
say(name) reassigns Baal to its code body as a closure and makes it captured a ghost method, that's how things work. But I'm trying to avoid eval ..
So .. let me reword the question:
How do I make a nonexistent(and not a member or global) method invocable without using eval?
Let me rephrase your question, just to make sure I’ve got it. Given a function, you want to put a new variable in its scope, without that scope being the global scope or a scope shared between the caller and the subject, without using eval (or the equivalent new Function and other hacks depending on the environment).
You can’t.
In the case you just mentioned, you could define one function, base(), that uses arguments.callee.caller.
Don’t do that.
The short answer: You don't.
That scope is not available. If you were to attach the scope then it would be available inside of the scope used. You could then access the method handles. I assume this is not what you were looking for, but here is what that would look like. demo
function say(name){
var methods = {};
methods.Baal = function(){
alert("!");
};
return methods[name];//this could invoke as well: methods[name]()
}
var handle = say('Baal');
handle();
What your evals break down to is something along these lines (although with dynamic content from string building - this is the end result)
function say(name) {
var Baal = (function () {
function ghost() {
alert('!');
};
return function(){
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
})();
Baal();
}
say('Baal'); // or just Baal();
Note that the meat of what happens here is from the function Baal, namely that it calls a hardcoded ghost() which in turn calls a hardcoded alert. Why go through all of this trouble to access a hardcoded function?
A better way would be to inject this function as a callback which expects some parameters to be injected.
jsFiddle Demo
function say(callback){
var params = "!";
if( typeof callback == "function" ){
callback(params);
}
}
say(function(params){
alert(params);
});
It's very difficult for me to read through your code and figure out what you are trying to accomplish with it, but it appears that you are trying to introduce a variable into the current scope so that you can call it. You cannot do this in javascript with the method that you demonstrated. Scoping only ever "flows down". By that I mean that a variable or function defined within a function will only be available to that function and any other functions defined therein. Your function named ghost will only ever be available within the function where it is defined, regardless of when that function is evaluated.
What you can do, however, is write a function that returns a function. You can then call that function and assign the result to a variable in the scope where you want to expose functionality. Doing that would look something like this.
function defineSpecialAlert() {
return function(name) {
alert(name + "!");
};
}
var newlyDefinedMethod = defineSpecialAlert();
newlyDefinedMethod("Baal");
So if I understand, it seems like you want to create an alias of eval: Something like
#Note this code is not intended as a solution, but demonstrates
#an attempt that is guaranteed to fail.
#
function myAlias(ctx) {
eval.call(ctx, 'var ghost = 42');
}
myAlias(this);
alert(ghost);
Javascript allows many funky sleight-of-hand tricks especially with closures, but this is maybe the one impossible thing that javascript cannot do. I've tried at length to do this exact same thing, and I can tell you that you'll run into nothing but complaints from the browser, saying that eval cannot be re-contexted or aliased in any way.

Calling the function immediately on the call of the page

var ObjectLiteral = {
myName:function() {
}
}
I want to call the myName function immeditetly when the page is
loaded.
I am not sure hot to write a self calling function inside an
ObjectLiteral...
You can't assign a function while simultaneously calling it (since calling it means that its return value gets assigned instead). You have to do this in two steps.
var ObjectLiteral = {
myName:function() {
}
};
ObjectLiteral.myName();
Just because no one mentioned it:
var ObjectLiteral = {
myName: function() {
console.log('myName was called!');
return arguments.callee;
}()
}
Since arguments.callee is deprecated in ES5, we would need to give the method a name:
var ObjectLiteral = {
myName: function _myName() {
console.log('myName was called!');
return _myName;
}()
}
Done. The method would get called at pageload and would still be callable later on. The caveat of doing it that way is the this context value which is replaced with window or undefined (strict) on the self-executing method. But you could apply some magic to solve that aswell. For instance, invoking .call(ObjectLiteral) in es3 or .bind(ObjectLiteral) in es5.
var ObjectLiteral = {
myName: function _myName() {
console.log('myName was called!');
return _myName;
}.call(ObjectLiteral)
}
Looks like I was wrong (damn!). The idea ok, but the assignment to ObjectLiteral is not done on the first invocation of myName. Therefore, the above code will only run from the second call on, which of course makes it useless anyway. You would need to invoke another context, but that would be just overkill.
It still does work after all, but it screws up if you need to access this, otherwise its a fine solution I think.
For your first question:
The simplest possible answer is to add this line to your script:
window.onload = ObjectLiteral.myName();
A better answer is to include that line somewhere in a larger function assigned to window.onload:
window.onload = function () {
....
ObjectLiteral.myName();
}
An even better answer is to scope things properly in case window has been reassigned.
For the second question, what to you mean by self-calling? (EDIT: n/m, Quentin answered)
Taking into account you want to execute your code after page load, jQuery is very suitable for that:
$(function() {
// called then page loaded..
var ObjectLiteral = {
myName:function() {
}
};
ObjectLiteral.myName();
});

call a specific javascript function when multiple same name function are in memory

I need to call specific js function. The problem is many time runtime situation can come where another js file may contain same name function. But i need to be specific that which function i am suppose to call.
Function overloading is not my solution.
Thanks and regards,
Tanmay
you're going to have to do some reorganization of your resources and use namespacing where you can.
if you have a method named saySomething defined twice, you would move one of them to an object (whichever suits your needs better).
var myNS = new (function() {
this.saySomething = function() {
alert('hello!');
};
})();
and the other defintion can be moved into a different object or even left alone.
function saySomething() {
alert('derp!');
}
you can now call the saySomething method like
saySomething(); // derp!
myNS.saySomething(); // hello!
edit: since it was brought up in comments, this
var myNS = {
saySomething: function() {
alert('hello!');
}
};
is equivalent to the first code block, in simpler form (if i'm remembering correctly).
At least in firefox, when you have two functions with the same name, the second will overwrite the first one.
So, you can't call the first one.
Try it:
function a() {alert(1);}
function a() {alert(2);}
a(); // alerts '2'
See in jsfiddle.
In javascript, similarly named functions automatically override previous function defined with the exact same name.
Let's say your page includes 1.js and 2.js and both of them define the same function, for example say, display(). In this case, based on which js file is included the last, the definition of 'display()' in that file will override all other prior definitions.
I use function scope to limit the scope of variables and functions
Here is an example:
// existing function in JavaScript
function one() {
console.log('one');
}
one(); // outputs one
// inserting new JavaScript
(function() { // anonymous function wrapper
'use strict'; // ECMAScript-5
function one() {
console.log('two');
}
one(); // outputs two
})(); // end of anonymous function
one(); // outputs one
I hope that helps
:)

Categories

Resources