A local function in the closure declares a variable with the same name which exists in the closure. So, how could we access closure's variable from the local function?
function closure()
{
var xVar;
function func1()
{
var xVar;
// how to distinguish local and closure scopes.
return xVar;
}
return function () { return func1(); };
}
Creating a private object and making private variables as properties of this object could help. But I am wondering if there is a better and neat solution. Can a scope chain help?
I have edited to make it a complete closure. Anyway, closures are not much concern here, it could be considered for inner functions however, there may be a solution with closures somehow.
Thanks
You can't access the scope chain explicitly in JS. Your problem is the age-old one of variable shadowing, but it's that much more maddening because in JS, the scope chain is actually there at runtime, it's just not available for you to access.
You can play some tricks with rejiggering current scope if you use the hated with operator, but that (as well as arguments's caller/callee stuff) really just give you access to objects and functions with their properties. There's no way to say "give me what xVar means in the n-1 runtime scope from right here".
Variables defined in an inner scope hide variable declarations in an outer scope. The "better and neat solution" is not to reuse variable names that way.
In your example the xVar variable is not a closure, because you redefined its scope to each function. To use that variable as a closure continue to declare it with the var command in the closure() function and then do not declare it with the var function in the func1() function. Instead just use the variable immediately in func1().
There is not an easy way to test if a function is a closure or a local variable. You would have to perform some sort of flow control test and then analyze assignments, where assignments occur, and where assignments do not occur. Then you must compare those results. You could write a tool, in JavaScript, to perform that analysis upon a given input and write you a report as output.
Related
var variableOne;
var variableTwo;
var variableThree;
function veryInterestingFunction() {
var variableFour;
if(a){
variableFour = 'Good';
}
else {
variableFour = 'Decent';
}
console.log(variableFour);
}
$(window).on('scroll', function(){
veryInterestingFunction();
});
Here I have some variables in the global scope, a function declaring a variable and assigning a value to it, and calling this function on scroll.
This way on every scroll you are going to declare the "variableFour" which is not a good practice, right?
However I don't want to crowd the global scope with unnecessary variables and also can't use an IIFE. Is there a "best practice" way to declare the variable outside the function and still only possible to use it inside the scope of that function ?
http://jsfiddle.net/2jyddwwx/1/
to declare the variable outside the function and still only possible to use it inside the scope of that function ?
I guess, that's impossible
When I don't want to crowd the global scope, I will declare one global object, for example App = {}, and instead of global variables, I use it's properties.
App.variableOne;
App.variableTwo;
App.variableThree;
Or you can use classes in ES6
I don't think there's anything wrong with your code sample, I seriously doubt variable declaration is ever going to slow down your code. I'd definitely only start to worry about this kind of thing when you're absolutely certain it's causing issues (it won't), otherwise it might be wasted effort.
If you really want to optimize this, one thing you might be able to do is debouncing the veryInterestingFunction calls - that is if you don't necessarily need to respond to every single scroll event (depends on your logic).
As per your question, IIFE/function closure is essentially the only way to limit scope in JavaScript that I know of, so if you can't use that, I don't see any other option.
There is no problem in declaring an empty variable into your scope. If it is not global, it belongs to the scope.
And there is no need to fear for performance. If you declare variables within your scope, the Javascript garbage collector will empty that for you. Take a read at this article
The teachers at my school are teaching us we have to specifically declare function variables like so:
function something(var1, var2)
{
var var1, var2;
console.log(var1);
console.log(var2);
}
something("Totally", "Cool");
However I can't seem to find any topics about this, so my question is, is this even required? Isn't it perfectly normal and OK to just leave the var var1, var2; out?
If so, is this stated somewhere in the W3C JavaScript documentation?
I mean it works either way, but if it works without... Cleaner code I'd say :P
Code I'm talking about: http://pastebin.com/y5B2aznc
Thanks!
in javascript, the scope of variables depends on how they are declared:
if you declare the variable when you define it, the scope of the variable is global
if you declare it using the var keyword, the scope of the variable is within the function
if you use the newer ES6 let keyword, the scope of the variable is within current block
so it is better to not use global variables and always limit the scope of your variables.
Here are a few references explaining the variable scopes in javascript:
What is the scope of variables in JavaScript?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
http://javascriptissexy.com/javascript-variable-scope-and-hoisting-explained/
you should also definitely read Douglas Crockford's Javascript, the good parts:
http://shop.oreilly.com/product/9780596517748.do
http://javascript.crockford.com/
edit:
in your particular case, it is not useful:
function something(var1, var2)
{
var var1, var2;
console.log(var1);
console.log(var2);
}
as you give those variables as parameters of the function, they are already declared within the function scope, so declaring them again as var is redundant, and you can safely remove that line.
function something(var1, var2)
{
console.log(var1);
console.log(var2);
}
In your particular case, all the variables passed as arguments are local variables just like the variables you declare with var. So re-declaring them with var is redundant.
But a better practice is to leave the arguments with their original values, and do stuff with them storing the results in other local variables. E.g.:
function something(var1, var2)
{
var varAlt1 = var1.toUpperCase(), varAlt2 = var2.toLowerCase();
console.log(varAlt1);
console.log(varAlt2);
}
Omitting the keyword var in the declaration will result in the variables being global and not having their scope limited to the function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
If you don't use the var statement then the variables will be created in the global scope which is the window object. This is a bad practice since you're polluting the global scope and can affect other scripts/functions.
I suggest you read on the var statement on MDN. Also, here's a nice article on Javascript scope.
Edit: I didn't notice that the variables you're declaring are also the function parameters. In this case, the var statement will have no effect since re-declaring an already declared variable is a no-op (does nothing).
If you want to know more about the var statement and how scope is handled in Javascript, may I suggest reading this article?
Can somebody please explain me why the following code works?
function getLastName()
{
fullName.lastName = "World";
}
function writeName()
{
fullName = {};
fullName.firstName = "Hello";
getLastName();
document.write(fullName.firstName + " " + fullName.lastName);
}
writeName();
For some reason, getLastName() can reach local its enclosing method's local state. How can this work? And also should I utilize this feature of Javascript or it is considered as a bad practice? If it is a bad practice, could you please explain why?
You can see the actual code working here at http://jsbin.com/atituk/2/edit
You don't have any local variables, that would require using the var keyword. All your variables are global and can be accessed anywhere within window, which is not considered good practice at all.
You have not used the var keyword against fullName inside the writeName function, you are therefore taking it from the scope outside writeName. It continues up the chain until it reaches the outer most scope, at which point it creates a global.
Globals are, in general, bad practise as they are hard to keep track of and more likely to be overwritten by accident (e.g. in a race condition).
If you were using strict mode this would create an error instead of a global.
You are using all variables of yours as global variables. So all are recognized everywhere. In order to have a better understanding of variable scopes in Javascript have a look at this great example https://stackoverflow.com/a/500459/655316
Whats the main purpose of Closures in JS. Is it just used for public and private variables? or is there something else that I missed. I am trying to understand closure and really want to know what are the main advantages of using it.
Closures have to do with how javascript is scoped. To say it another way, because of the scoping choices (i.e. lexical scoping) the javascript designers made, closures are possible.
The advantage of closures in javascript is that it allows you to bind a variable to an execution context.
var closedIn = {};
var f = function(){
closedIn.blah = 'blah'; // closedIn was just "closed in" because I used in the function, but it was defined outside the function.
}
in that example, you have a normal object literal called closedIn. It is accessed in a function. Because of that, javascript knows it has to bring closedIn everywhere it brings the function f, so it is available to f.
The this keyword is tricky. this is always a reference to the execution scope. You can capture the this of one context to use in another context as follows:
var that = this;
var f = function(){
that.somethingOnThat();
// `this` means the scope f, `that` means whatever 'this' was when defined outside of the function
}
This trick can be very useful somethings, if you are coding object oriented javascript and want a callback to have access to some external scope.
To quote from a Javascript book:
"Functions in JavaScript are lexically
rather than dynamically scoped. This
means that they run in the scope in
which they are defined, not the scopee
from which they are executed. When a
function is defined, the current scope
chain is saved and becomes part of the
internal state of the function."
So the clear advantage is that you can bring any object (functions, objects, etc) along with the scope chain as far as is necessary. This is can also be considered a risk, because your apps can easily consume lots of memory if you are not careful.
I think the best phrase to sum up the purpose of closures would be:
Data Encapsulation
With a function closure you can store data in a separate scope, and share it only where necessary.
If you wanted to emulate private static variables, you could define a class inside a function, and define the private static vars within the closure:
(function () {
var foo;
foo = 0;
function MyClass() {
foo += 1;
}
MyClass.prototype = {
howMany: function () {
return foo;
}
};
window.MyClass = MyClass;
}());
Closures are necessary in javascript due to the fact that most API's that require callback functions (for instance, an "onclick" function) do not provide other mechanisms to send parameters to those callback functions (or to explicitly set the "this" pointer). Instead, you need to use closures to allow the callback to access variables in the "parent" function.
I personally wish that they weren't necessary, since they can be hard to understand, make for hard to read code (it's not always clear what exactly is in scope), and make for weird bugs. Instead I wish there was a standard for callbacks that allowed you to send parameters, etc. But I accept that I am in the minority in this view.
As we know, the variables that are defined in functions, have local scope. We can't access them from outside of the function.
Problem 1:
local variables are created when the function is called and they will be destroyed when the function's task is finished. It means local variables have shorter life time than global variables. We may use global variables to overcome that issue.
Global variables are available when the program starts and are destroyed when it ends. They are also available throughout the program.
Problem 2:
Since global variables are accessible throughout the program, they are prone to change from everywhere.
What do we want?
We want to have data persistency + data encapsulation.
We can achieve them by using Closures. By using a closure we can have private variables that are available even after a function's task is finished.
Example:
function initCounter() {
let counter = 0;
return function () {
return ++counter;
}
}
// Each counter is persistent
const countJumps = initCounter();
countJumps();
countJumps();
alert("Jumps count is: " + countJumps());
const countClicks = initCounter();
countClicks();
countClicks();
countClicks();
countClicks();
alert("Clicks count is: " + countClicks());
// Each counter is isolated
alert(counter); // Error: counter is not defined
lets say that I have the following scenario:
var namespace = {};
(function($)
{
$.extend(namespace,
{
test1: function(someArray, someObj)
{
for(var i= 0, ii= someArray.length;i<ii;i++)
{
var text = someObj[someArray[i]];
// do something with text
}
},
test2: function(someArray, someObj,i,ii,text)
/*
see that the i,ii,text are unused parameters,
that will be used instead of variables
*/
{
for(i= 0, ii= someArray.length;i<ii;i++)
{
text = someObj[someArray[i]];
// do something with text
}
},
});
})(jQuery);
Now, the result of the test1 and test2 are the same... but what about the performance, memory usage...
Is there any difference between declaring the i,ii, test variables in the two ways presented above ?
I think that the test2, for example, is probably more efficient because the variables are in the local function scope so after the function exits, the execution context is destroy, releasing the resources used for the arguments... the variables will not be assigned to the global object 'window'.
So what method is performing best? and why?
[Edit]
Thanks all for your answers !
There is no problem if the code has readability issues... I`m only interested now about the performance/memory usage.
If you do not declare your variables with var i then they become implicitly global.
Always declare your variables. If you did any benchmarking on that you would find that declared local variables are actually faster then implied global variables. Also you don't leak to the global state that way.
Benchmark!.
As you can see the performance is identical.
In terms of memory usage, local variables (test1) are probably better as the compiler doesn't have to remember that the function has 5 parameters.
But that's a nano optimisation If you care about performance differences of this caliber write assembly instead. Go for readable and maintanable code.
[Edit]
Didn't notice "local" variables in method parameter. That is a readability killer! Don't do that. You will find that test1 is probably still more efficient.
Why don't you profile your code?
The variables are also local in test1. You are declaring them with var i.
There is no difference between these methods.
The variables in "test1" are all declared with var, so they're not global. Those two should be essentially the same.
test1 is faster, because every time JavaScript looks for symbols (such as a variable name) it starts by looking in the local scope. So by using global scope it has to look in more places to find the symbols. The same applies for parameters, but they are better than globals.
It may be miniscule, but declaring a new variable (text) in every iteration would require new memory allocation I believe. Though I'm not sure how javascript handles that. I usually declare variables beforehand and then assign values afterwards for that reason, but that is only because someone said "hey you should do it that way" and presented the same argument.