I've seen the same code written both ways and wonder if there's any tradeoff between them.
Method 1:
(function(i) {
// Do something to i now
}(global_variable))
Method 2:
(function() {
// Do something to global_variable now
}())
Why would you pass a global variable to a function if it's going to exist in that scope anyway?
In this case, it gives clear instructions that this function uses a global and creates an easier to type alias. Also, it makes accessing the variable a little faster because it doesn't need to search all the scopes until it finds it in the global scope.
In the case of regular functions, not an iife as in your example, it makes your function more testable because you can mock the global that is passed in more easily.
for aliasing purposes for example:
(function(leeloo){
//inside here you can use the short term
})(LeeloominaiLekataribaLaminaTchaiEkbatDeSebat)
//this would be similar, it's a matter of preference
(function(){
var leeloo = LeeloominaiLekataribaLaminaTchaiEkbatDeSebat;
//...
})()
or to enclose a value, like this example:
(function($){
//in here, $ preserves the passed/injected value,
//even if the global value changes
})(jQuery.noConflict())
this way you could even use multiple versions of jQuery in the same page.
You might want to use the first example when you don't want to permanently change the value of global_variable, for some reason. E.g. after executing this code the local copy will be changed but the global variable will be unchanged.
global_variable=true; (function(i){ i=false; return i; }(global_variable));
This code however, obviously alters global_variable:
global_variable=true; (function(){ global_variable=false; }());
Edit: somewhat tangentially, this variation looks like it alters the global variable, but it doesn't because calling the function creates a shadow copy of the global variable. You should probably avoid this pattern since it's likely to create confusion:
g=true; (function(g){ g=false; return g; }(g));
Related
I was looking for this but could not find a question as simple as I want it. The problem is really simple: In angular js, should I use local variables, or properties of this (in cases when I don't need to use this).
Example:
// I need "this" here because I need this collection in template
this.collection = SomeService.fetchCollection();
// I can use either "foo" or "this.foo" here, which one is better?
this.fetchSomeData = function(type) {
var foo = AnotherService.foo(type);
return FooService.call(foo);
}
A local variable, so it can be cleaned up as soon as the method exits. Otherwise it would stay unused in the parent's namespace.
But in 99% of cases that will have no real-world effect, so it doesn't matter.
Because you haven't declared 'foo' as a var it will be a global here, which is bad. You should at least prefix it with 'var' so it's scoped to the function and not globally; it shouldn't be available outside the function.
in my opinion it is a good practice not to reveal everything and keep it encapsulated - for example, it avoids moving logic to view which is bad
also, consider that you have a for loop iteration over i variable - would you also use this.i for such purpose?
I see a lot of this in older JavaScript
(function (w){
w.bar = 'baz';
})(window);
What is the advantage of the above, over
(function(){
window.bar = 'baz';
})();
same goes for any global variable, or variable defined outside the IIFE.
Makes it explicit that you are using (and probably modifying) globals in the function.
Allows you to modify the behavior in the future. Maybe you have a mockWindow for a unit test. Maybe you are using Node.js and you don't have a window, but want to add to the globals var instead.
p.s. IMO the trivial performance gain mentioned by #Rayon is a red herring.
In practice there is not much (any?) difference wit the example you have given, but you have probably oversimplified it from the code you are actually looking at.
In a more realistic program, you will have scopes and calls backs which are triggered and run in the eventloop asynchronously, and you are binding the variable to a specific instance in a closure -- so;
(function (w){
setTimeout(function(){w.bar = 'baz';},100);
})(window);
window = window2;
The bar is still being set in the original window, since that is what is bound to w - where in
(function (){
setTimeout(function(){window.bar = 'baz';},10);
})(window);
window = window2;
It will be set in the instance window2, since that is how the window is bound when the execution of the code eventually happens.
In this example "window" is a global variable, but the same is the case regardless of the scope of the variable that is bound.
Passing window is done because local variables are easier and faster to access than global variables ...this may show slight difference in performance . The method really comes in handy with module patterns and/or dependency injection .
Example
var moduleFirst = (function(){
var name = "harry";
return {
firstparam : name
}
})();
var moduleTwo = (function(x){
console.log(x.firstparam);
})(moduleFirst)
Output will be : harry
So when window gets passed in IIFE ; all of its revealed methods are available in a local variable .
By passing global objects like window, document, $ to IIFE(Immediately Invoked Function Expression) one can enhance the performance by reducing the scope lookup time.
Remember Javascript looks for property at first in local scope and way up chaining till global scope. So accessing window object at local scope reduce the lookup time.
When I call a function, a local scope is erected for that call. Is there any way to directly reference that scope as an object? Just like window is a reference for the global scope object.
Example:
function test(foo){
var bar=1
//Now, can I access the object containing foo, bar, arguments and anything
//else within the local scope like this:
magicIdentifier.bar
}
Alternately, does anyone have a complete list of what is in the local scope on top of custom variables?
Background: I'm trying to get down to a way of completely shifting to global scope from within a function call, the with statement is a joke, call works a little better, but it still breaks for anything declared in function scope but not in global scope, therefore I would declare these few cases in global scope, but that requires me to know what they are. The IE function execScript makes a complete shift, but that only solves the problem for IE.
Note: To anyone loading JavaScript dynamically, setTimeout(code,1) is a simple effective hack to achieve global scope, but it will not execute immediately.
No, there's no way to reference the variable object of the execution context of a function binding object of the variable environment of the execution context (that's what that thing is called [now; hence the strikethrough]; details in §10.3 of the specification). You can only access the limited view to it you get with arguments (which is very limited indeed).
Usually when I've wanted to do this, I've just put everything I wanted on an object and then used that (e.g., passed it into a function). Of course, any functions created within the context have access to everything in scope where they're created, as they "close over" the context; more: Closures are not complicated.
I know this is hugely late, and you're probably not even slightly interested any more, but I was interested in the feasibility of this too and you should be able to make a work around of some sort using:
(function(global) {
var testVar = 1;
global.scope = function(s) {
return eval(s);
}
})(this);
then running:
scope('testVar'); // 1
returns the variable from within the closure. Not particularly nice, but theoretically possible to wrap that in an object, perhaps using some validation and getters and setters if you needed?
Edit: Having re-read the question, I assume you'd want to access it without having to specify a function in the scope itself, so this probably isn't applicable. I'll leave this here anyway.
Certain versions of Netscape had a magic property in the arguments object that did what you're looking for. (I can't remember what it was called)
What about something like this?
<script type="text/javascript">
var test = {
bar : 1,
foo : function () {
alert(this.bar);
}
}
test.foo();
</script>
You don't need a keyword to reference a variable in the local scope, because it's the scope you're in.
I'm new to JavaScript, and have a simple (I presume) question regarding best practices for accessing variables in functions:
When should I declare a global variable, as opposed to simple passing a value into a function?
Declaring a global variable should only be used as an option of last resort.
Global variables are bad in general and especially so in javascript. There is simply no way to prevent another piece of javascript from clobbering your global. The clobbering will happen silently and lead to runtime errors.
Take the following as an example.
// Your code
myParam = { prop: 42 };
function operateOnMyParam() {
console.log(myParam.prop);
}
Here i've declared 2 global variables
myParam
operateOnMyParam
This might work fine while testing your javascript in isolation. However what happens if after testing a user combines your javascript library with my javascript library that happens to have the following definitions
// My code
function myParam() {
console.log("...");
}
This also defines a global value named myParam which clashes with your myParam. Which one wins depends on the order in which the scripts were imported. But either way one of us is in trouble because one of our global objects is dead.
There are many, many reasons.. but an easy one is.. The argument of a function only exists in the function, while it's running. A global variable exists all the time, which means:
it takes up memory until you manually 'destroy' it
Every global variable name needs to be unique
If, within your function.. you call another function.. which ends up calling the first function, all of a sudden you may get unexpected results.
In short: because the function argument only lives for a really short time and does not exist outside the function, it's much easier to understand what's going on, and reduced the risk of bugs greatly.
When dealing with framework-less JavaScript I'll store my simple variables and functions in an object literal as to not clutter up the global namespace.
var myObject = {
variableA : "Foo",
variableB : "Bar",
functionA : function(){
//do something
//access local variables
this.variableA
}
}
//call functions and variables
myObject.variableA;
myObject.functionA();
When I call a function, a local scope is erected for that call. Is there any way to directly reference that scope as an object? Just like window is a reference for the global scope object.
Example:
function test(foo){
var bar=1
//Now, can I access the object containing foo, bar, arguments and anything
//else within the local scope like this:
magicIdentifier.bar
}
Alternately, does anyone have a complete list of what is in the local scope on top of custom variables?
Background: I'm trying to get down to a way of completely shifting to global scope from within a function call, the with statement is a joke, call works a little better, but it still breaks for anything declared in function scope but not in global scope, therefore I would declare these few cases in global scope, but that requires me to know what they are. The IE function execScript makes a complete shift, but that only solves the problem for IE.
Note: To anyone loading JavaScript dynamically, setTimeout(code,1) is a simple effective hack to achieve global scope, but it will not execute immediately.
No, there's no way to reference the variable object of the execution context of a function binding object of the variable environment of the execution context (that's what that thing is called [now; hence the strikethrough]; details in §10.3 of the specification). You can only access the limited view to it you get with arguments (which is very limited indeed).
Usually when I've wanted to do this, I've just put everything I wanted on an object and then used that (e.g., passed it into a function). Of course, any functions created within the context have access to everything in scope where they're created, as they "close over" the context; more: Closures are not complicated.
I know this is hugely late, and you're probably not even slightly interested any more, but I was interested in the feasibility of this too and you should be able to make a work around of some sort using:
(function(global) {
var testVar = 1;
global.scope = function(s) {
return eval(s);
}
})(this);
then running:
scope('testVar'); // 1
returns the variable from within the closure. Not particularly nice, but theoretically possible to wrap that in an object, perhaps using some validation and getters and setters if you needed?
Edit: Having re-read the question, I assume you'd want to access it without having to specify a function in the scope itself, so this probably isn't applicable. I'll leave this here anyway.
Certain versions of Netscape had a magic property in the arguments object that did what you're looking for. (I can't remember what it was called)
What about something like this?
<script type="text/javascript">
var test = {
bar : 1,
foo : function () {
alert(this.bar);
}
}
test.foo();
</script>
You don't need a keyword to reference a variable in the local scope, because it's the scope you're in.