I know there are a lot of posts here and elsewhere about selfexecuting functions but I still have some questions after reading posts.
why would I ever assign a self-executing function to a variable? If seems that they execute themselves anyways.
var myFunc=(function() {
console.log('Hello World');
})();
I read a lot that the reason to use self-executing functions is to keep variables private. If I have a not self-executing function, everything I define inside that function is gonna be private anyways?!
(function() {
var name="my Name"
console.log(name);
})();
vs.
function() {
var name="my Name"
console.log(name);
};
//its the same
So I dont quite understand how self-executing functions are to keep local scope (as you can do that using not self-executing functions) so the only reason I see is to use them when you want to execute automatically for example on page load.
Thanks!
just one more question:
var test=(function myFunc(){
var name="Hello World"
return {
test1: function(){
return name;
},
test2:function(){
return name+"1"
}
}
})()
test.test1()
vs
var test=function myFunc(){
var name="Hello World"
return {
test1: function(){
return name;
},
test2:function(){
return name+"1"
}
}
}
test.test1()
--> what exactly happens here that because of IIFE I can actually execute test.test1() and not with a regular function?
You usually wrap your functions in a anonymous function when you want to keep your scope contained. This is also part of the module pattern which is still pretty popular:
https://toddmotto.com/mastering-the-module-pattern/
Then you can assign the outcome of that IIFE to a variable so your scope can only be accessed by calling that variable.
myScope.myLocallyScopedProperty or myScope[myLocallyScopedProperty]
Your other function needs to be called manually and it also accessible from anywhere.
I suggest reading the article by Todd Moto it explains a lot.
If that IIFE doesn't return anything, then there's indeed absolutely no use to assign it to anything. Though there may of course be examples of IIFEs returning something you want to use later; in that case the IIFE is a private scope to set up some object for example:
var foo = (function () {
var bar = 'something';
// here be dragons
return baz;
})();
This gives you a private scope to assemble baz without unnecessarily leaking temporary variables into the global scope.
There's no difference in those examples, except that the second one doesn't execute and therefore never does anything. Scoping and the purpose for the scoping are unchanged.
First, briefly, these are not self-executing functions. (That would be a recursive function.) These are inline-invoked function expressions (IIFEs). The function doesn't call itself, the expression calls the function.
why would I ever assign a self-executing function to a variable?
That's not what that code does. It assigns the result of calling the IIFE to the variable. You'd use it when you want that result, for instance:
var x = (function() {
var n = 0;
return {
increment: function() { return ++n; }
};
})();
console.log(typeof x); // "object"
console.log(x.increment()); // 1
console.log(x.increment()); // 2
x doesn't receive the IIFE, it receives what that IIFE returns — in this case, an object with a function on it.
I read a lot that the reason to use self-executing functions is to keep variables private. If I have a not self-executing function, everything I define inside that function is gonna be private anyways?!
Yes, that's true. You use an IIFE when you only need to do what's inside the IIFE once. Otherwise, absolutely, you define the function, give it a name, and then reuse it wherever you need it. The variables inside the function are indeed private to it (unless exposed in some way), and are specific to each call to the function.
1: To assign an IIFE to a local Variable makes sense for something like that:
var getID = (function () {
var id = 0;
return function () { return id++; };
})();
This way you can get new IDs without running the risk to reset the internal counter from anywhere else in the code, except by redeclaring the variable.
2: Basically you create Scope by creating a function. But if you do not execute it, well, it doesn't do anything. So if you have that:
function () { return 'foo' };
How do you want to call it if it is not assigned to a variable or does not have a name? By itself it wont do anything, since it is not called. Something like that is dead code and can safely be removed.
your first thing has no sense whatsoever:
var myFunc = =(function() {
console.log('Hello World');
})();
myFunc is not a function and it is undefined.
The sense, as I see it, for a self executing function is to package some code that has to be executed right away.
var p1=1, p2=2, obj = {
prop: (function(x,y){ return x+y;})(p1, p2)
}
OR
avoiding overwriting already defined functions/objects in the case your script will be inserted in a already existing application and also creating a kind of private methods, if you like:
function aFunction() {
console.log('a code');
}
(function(w) {
function aFunction() {
console.log('b code');
}
w.run = function() {
aFunction();
};
})(window)
aFunction();
run();
You use self executing functions to expose only what you need out of a scope. I think I have a somewhat clear example:
let myObject = (function(){
let privateVariable = "I'm private";
function privateMethod() {
//private method
};
function methodToExpose() {
//this method I will expose
}
//what is returned here, is what is public
return {
PublicMethod: methodToExpose
//other public properties
}
}());
So, the function gets executed immediately, and what happens is I have an object that is defined by what I returned from the function.
Another example I could give you is to retain variables of the current scope inside a closure, but you wouldn't really use it that much, since we now have let. A practical example:
<span id="1">old</span>
<span id="2">old</span>
<span id="3">old</span>
<span id="4">old</span>
<script>
var toPrint = "";
for (var i = 1; i <= 4; i++) {
toPrint = "new: " + i;
document.getElementById(i.toString()).addEventListener('click', function(event){ event.target.innerHTML = toPrint; })
}
</script>
When you click on a span, the value will be replaced with the value... "new: 4"!
That's because when you finished executing, that's the value that toPrint has. The function assigned to the click event retrieves that toPrint, and at the time it retrieves it, it is "new: 4". We solve this with closures:
<span id="1">old</span>
<span id="2">old</span>
<span id="3">old</span>
<span id="4">old</span>
<script>
var toPrint = "";
for (var i = 1; i <= 4; i++) {
toPrint = "new: " + i;
document.getElementById(i.toString()).addEventListener('click', function(event){
var currPrint = toPrint;
return function(event){ event.target.innerHTML = currPrint ; };
}())
}
</script>
By using a self executing function, we save the current value of toPrint in the currPrint variable inside a local scope. When we later click on a span, the function assigned to the click even will use the variable currPrint, which contains the value that toPrint had at the time the function was assigned, not the value that toPrint has at finished execution.
Note that this is solved also by using let instead of var, but still, it's an example of self-executing functions :)
In the form of IIFE (or immediately invoked function expressions), they can then be used to create plugins or used as namespaces and attached to window / jquery / or other global level object for use later.
When you name a function like assigning anonymous function to a variable, you can use it later by calling the variable with parentheses, in your example, defined myFunc with
var myFunc=(function() {
console.log('Hello World');
});
Use it later in code as myFunc();
In your example, you are storing the output of function directly in variable, by calling it immediately, and there is no output to be stored.
So, if you later write console.log(myFunc);, there is undefined as output.
Better IIFE example from your code samples is the one mentioned below.
(function() {
var name="my Name"
console.log(name);
})();
It executes, does a console.log and that's it. Adds nothing to namespace or the global object in your case.
The last of your examples defines a function, does not execute it then, and since it does not have a named variable assigned, or a name, it gives syntax error and cannot be used later in code. So, below example is useless.
function() {
var name="my Name"
console.log(name);
};
You have added two more examples with var test = function myFunc. First one will work fine with test.test1(). For the second one, you need to evaluate test as a function first and then call its function, like test().test1().
I guess you miss something here. Just to make basic things clear - if you assign a self executed function to a variable the actual return value of the function when executed at this time is assigned to the variable and not the function itself.
var myFunc = (function() {
console.log('Hello World');
})();
myFunc(); // will throw error: TypeError: myFunc is not a function
myFunc === undefined
var myFunc = (function() {
console.log('Hello World');
return 'japp';
})();
myFunc(); // will throw error: TypeError: myFunc is not a function
myFunc === 'japp'
So why is this pattern around?
IIFEs are very useful to
limit the scope
if you declare
var test = 'test'; // var test actually will be assigned as a property of the current context (this)
window.test = 'test'; // so you pollute the global namespace which is not a good practice
so this would be mouch better
(function() {
var test = 'test';
})();
another very good thigs with IIFs is that you can achieve a design with "privates"
var myFunc;
(function() {
var i = 0; // i is available for myFunc with private access
myFunc = function() { console.log( ++i ) };
})();
myFunc(); // logs 1
myFunc(); // logs 2
I always thought that nested function invocations had access to the scope above them regardless of where the function was defined (in the below example I thought the printsomething function would have access to the "something" variable in the runeverything function). According to the below fiddle this is not the case. Does the function printsomething have to be defined (and not just invoked) within the outer function runeverything to have access to local variables defined within the other function runeverything?
This is important for me now because node modules are hoisted to the top when they are imported. This creates scoping problems for me!
function foo(){
function printsomething() {
$('#test').text(something || 'nothing');
};
var something = 'something';
function runeverything() {
printsomething(); //returns "something is not defined"
}
runeverything();
};
foo();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 id="test"></h1>
You need to have those functions embedded in another function in order to do that:
i.e:
function foo() {
function printsomething() {
$('#test').text(something || 'nothing');
};
function runeverything() {
printsomething(); //returns "something"
}
var something = 'something';
runeverything();
};
foo();
This way it will work since the scope of variable something is for function foo, where your functions are defined also.
Yes.
Scope is determined by where the function is defined and not by where it is called from.
To get access to data from the scope where a function is called: pass it as an argument.
For the sake of maintaining a namespace, I have code that looks something like this:
MyNamespace = function() {
var foo;
//other private vars
//some private functions
//return certain functions which will be publicly called through MyNamespace
return {
"pubFunc1": function() {/*do stuff*/}
}
}
I'd like one of my public functions to be able to take a function as a parameter. The function being passed in would look something like this:
function(state) {
//do something with the passed in state
}
This function would be passed into the first anonymous function. From there, as implied by the parameter, the first anonymous function would pass its state (with this) to the function that was just passed in. The problem I run into is that the this of an anonymous function refers to the global window, not to the anonymous function.
What I really need is the ability to pass in a function and give it full access to the private variables and functions within my namespace function. Does anyone know a good way to do this?
Javascript uses lexical scoping, that is, only functions physically located inside an outer function have access to its scope (vars). There's no way to make function's vars accessible for any function defined outside.
So your only option to make "private" vars into "protected" properties and pass the properties bag to the callback:
MyNamespace = function() {
return {
_foo: "something",
_bar: "else",
pubFunc1: function(callback) {
callback(this._foo, this._bar) //or
callback(this)
}
}
}
I had this code:
Javascript
(function() {
function read() {...}
})();
HTML
<body onload="read()">
Console said, read is undefined.
After deleting the IIFE it worked, why?
Thanks. :)
Here's a long but satisfying explanation about JavaScript scope and closures.
Since you declare read inside a function, it is local to that function.
Anything you declare inside a function will be local to it.
You can explicitly put it into global scope by assigning it as a property to window:
(function() {
function read() {...}
window.read = read;
})();
Writing
(function() {
function read() { ... }
})();
Is very nearly the same thing as writing
(function() {
var read = function() { ... } //this is different, but not significantly so
//for purposes of teaching this point
})();
and I think you should already understand why a var declared inside a function is not available outside of that function's scope.
The behavior of a function definition (function read() { ... }) is slightly different from the behavior of assigning a function expression to a variable (var read = function() { ... };) in terms of when the name of the function and the function become associated, but the two are otherwise identical.
Because it isn't defined globally. It's only been defined within the scope of that immediately invoked function. To make it global either use this:
function read() {...}
(function() {
...
})();
Or this:
(function() {
window.read = function() {...}
})();
Or better yet, just bind the onload event within the immediately invoked function:
(function() {
function read() {...}
window.onload = read;
})();
In this case the definition of read is inside the IIFE. This limits the scope of the function to the IIFE and any child functions inside of it. The handler for onload is executed in the global scope and hence doesn't have access to read
A couple of days ago I have learned on my own example how bad global variables and functions are. So apparently the best solution is NOT to use them, however sooner or later I will need to reuse my variables and functions over and over again.
So my question is: Can I reuse my functions and variables without declaring them globally? Can it be done?
For example, I want to reuse my alertBox function and my containsP variable couple of times:
DEMO: http://jsfiddle.net/ajmyZ/
//I am BAD GLOBAL FUNCTION inside var
//But I am reusable!!!
var alertBox = function () {
alert("Hey I am BAD function!!")
}
$(document).ready(function () {
//I am BAD GLOBAL var
//But I am reusable TOO!!!
var containsP = $("div p:first");
containsP.click(function () {
alert("Hi BAD var HERE!!");
});
$("p").eq(1).click(function () {
alertBox();
});
//I am the NICEST function here
//but I am NOT reusable :(
$("p").eq(2).click(function () {
alert("I am the NICEST function here!!");
});
});
I guess the simplest way to avoid clobbering the global object is just to create your own "application context". You can do that, by creating a self-invoking function which wraps your whole js-code within each file.
(function( win ) {
"use strict";
var still_global_but_only_in_this_anonymous_closure = true;
$(document).ready(function() {
// ...
// accessing the global object:
win.some_global_property = true;
});
}( this ));
Actually, you're already creating such a local context with your anonymous function you pass into .ready(). This is just the more explicit way. That self-invoking method, just calls itself with the global object as argument (where you still can explicitly access global variables). Furthermore, by invoking "use strict"; you're protected from accidently creating global variables alá "Ops_I_Forgot_The_Var_Statment = true;
The code you posted has no global variables. A variable declared inside of a function (in the case of your example, the anonymous document.ready handler) will never be global unless you make one of two mistakes:
forget the var keyword, making an implicit global
explicitly say window.myVar = ...;