I'm coming from an Actionscript background and (very late to the party) I am trying to learn JavaScript. I am going through this AngularJS - Video Tutorial For Beginners on YouTube (it's pretty good) and saw something really basic that I don't understand.
At line 5 the var workcount is defined. Then two anonymous functions are defined and returned in an object. The functions reference workcount but isn't workcount in a different scope? Is this like blocks in Objective-C where local vars remain accessible within the block. Is there a name for what this is?
Or if a function "knows about" vars previously defined in its scope, would the function task2 "know about" task1?
It bugs me that I can't make sense of this.
Update: Thanks for all the replies. I get it now – and while I have seen the term "closures" before, I never understood it (it seems a not very descriptive term. In reading up, I saw the term "stack-frames" and then the light bulb lit up: stack... frame of reference);
var createWorker = function(){
var workCount = 0;
var task1 = function(){
workCount += 1;
console.log("task1" , workCount);
};
var task2 = function(){
workCount += 1;
console.log("task2" , workCount);
};
return {
job1: task1,
job2:task2
}
};
worker=createWorker();
worker.job1();
worker.job2();
Output:
task1 1
task2 2
Just note that the variable and the two anonymous functions are wrapped inside the same function (let's call it a parent function). So the scope of this variable is available within this parent function.
So now this variable acts as a global variable for these two inner functions But the scope is limited to the parent function. Both the inner functions share the same variable.. Changing the value of the variable in one function will have effect in other function too..
So taking the logic in the post Let's say we execute task1 and task2 one after the other. The variable is initially set to 0. Then in your task1 it's incremented by one. Which makes the variable value 1 (0 + 1). Now in task two also its increased by one, making its value 2 (1 + 1).
This scope concept is called as closure in JavaScript.
This is called a closure in JavaScript.
The scope of a closure in JavaScript is lexical, which means that everything that is contained within the function the closure belongs to, has access to any variable that is in it
Basically createWorker is a scope and since task 1 and task 2 are declared inside createWorker they have access to all the variables declared in createWorkers scope.
But createWorker does not have access to any variables declared inside task 1 and task 2.
Yes, functions are aware of everything in their scope, including each other.
There are two parts to your question.
The second part is easy to answer first: all variables and functions in a scope are "hoisted," allowing you to use a variable before you declare it:
x = 5;
var x;
console.log(x); // Gives 5
Back to the first part of your question: in terms of scope, I won't expand too much on it since it is a widely covered topic on this and other sites. w3schools has a good guide on this.
Basically, it boils down to global and local scope. Global scope works as you might imagine, with the variable (or function) being available globally:
var x = 10;
function foo() {
console.log('Global scope! ' + x);
}
Local scope is, basically, for everything within a closure (a topic well beyond this question), which functions are:
function foo() {
bar(); // This will work, since foo and bar share scope
foobar(); // This will not work: foobar is only in scope within bar
}
function bar() {
function foobar() {
console.log('foobar');
};
console.log('bar');
foobar(); // This will work, since foobar is defined within bar's local scope
}
Things get a little more complicated with var declarations. This is being greatly simplified by the ES6 let declaration. Read more.
And by the way, while your functions are anonymous, they aren't really since you are saving references to them. Functionally, the two examples below are perfectly equivalent:
// These give the exact same result
function foo() {}
var foo = function() {}
// You can use either by calling
foo();
This code illustrates how it works.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Closure JS</title>
<script type="text/javascript">
var createWorker = function () {
var workCount = 0;
var task1 = function () {
var t = t || 0;
workCount += 1;
console.log("task1: " + workCount);
console.log("task1 t: " + (t++));
}
var task2 = function () {
var t = t || 0;
workCount += 1;
console.log("task2: " + workCount);
console.log("task2 t: " + (t++));
}
return {
job1: task1,
job2: task2
};
}
var app = new createWorker();
</script>
</head>
<body>
<div>
<input type="button" value="task1" onclick="app.job1()" />
<input type="button" value="task2" onclick="app.job2()" />
</div>
</body>
</html>
Console output after several clicks on buttons:
task1: 1
task1 t: 0
task1: 2
task1 t: 0
task2: 3
task2 t: 0
task2: 4
task2 t: 0
It easy to see that task1 and task2 know about their parent scope and know nothing about each other and about their previous execution.
This way ball bounces.
You can write write your code as in below and javascript will interpret it the same.
var createWorker = function(){
var workCount, task1, task2;
workCount = 0;
task1 = function(){
workCount += 1;
console.log("task1" , workCount);
};
task2 = function(){
workCount += 1;
console.log("task2" , workCount);
};
return {
job1: task1,
job2:task2
}
};
What happens here is, variables are defined at the top of the enclosing function block. No matter in what order they are defined. So not only task2 knows about task1, task1 also knows about task2. However order of assignments in important. Consider the code:
function foo1() {
console.log("foo1: " + a);
var a = "Hello";
}
function foo2() {
var a = "Hello";
console.log("foo2: " + a);
}
function foo3() {
console.log("foo3: " + a);
let a = "Hello";
}
function foo4() {
console.log("foo4: " + b);
}
var b = 5;
foo1(); // undefined
foo2(); // Hello
try {
foo3(); // Throws ReferenceError
} catch (e) {
console.log("foo3: " + e.message);
}
foo4(); // 5
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
When foo1 tries to use a, it was defined but it was not assigned.
foo3 uses let instead of var. let is more intuitive for some
coming from other programming languages. But be careful as it is part
of ES6 specification and not widely supported yet.
foo4 works since b was defined before foo4 was
defined. b was assigned before foo4 was invoked.
JavaScript has some interesting variable scoping rules. Here is a quick overview:
x = 0; // Global, as no "var" keyword preceeds it. Btw: var is optional!
var x = 0; // This is scoped to it's parent fn. Child fn's can use it.
let x = 0; // This is similar to var, but has a special use case. (See below.)
As an added bonus, this next line of code looks like it's a variable declaration, but it's not. It defines a constant. It's part of the EcmaScript 2015 spec, AKA ES6. Here's what's new in ES6.
const x = 0; // This is a constant (locked variable) and can't be changed.
While both var & let are accessible by their immediate function & their children functions, here is where they're different: The let keyword can allow someone to make duplicates variables with the same name, from both inside of the parent & child functions! It just makes JS stranger!
Since workCount is defined inside of the parent createWorker function with the "var" keyword, then the task1 & task2 functions can change it's value, as they are children functions.
Check out the MDN specs on how the var & let keywords work.
So the answers to some of your questions are:
No, it's in the same parent "createWorker" function scope.
Unknown as I don't write ObjectiveC code. Someone else can answer that one.
Yes & No: Yes, because it can tell that task1 is a function, but No, because the code in task2's function block can't see inside of task1's function block.
task 2 would not know about variables created within task 1, task 1 and task 2 do know about workCount.
Related
From the MDN description of Function:
Note: Functions created with the Function constructor do not create
closures to their creation contexts; they always are created in the
global scope. When running them, they will only be able to access
their own local variables and global ones, not the ones from the scope
in which the Function constructor was called. This is different from
using eval with code for a function expression.
I understand,
var y = 10;
var tester;
function test(){
var x = 5;
tester = new Function("a", "b", "alert(y);");
tester(5, 10);
}
test(); // alerts 10
Replacing the tester = new Function("a", "b", "alert(y);"); with tester = new Function("a", "b", "alert(x);");, I will get
// ReferenceError: x is not defined
But couldn't understand the author's line-
...they always are created in the global scope.
I mean how is the new Function("a", "b", "alert(y);"); nested within the test fn is in global scope?
In fact, accessing it from outside the test fn will simply result in
Uncought TypeError:tester is not a function
Please elucidate.
In your example, "created in the global scope" means that tester will not have closure over x from test:
function test(){
var x = 5;
tester = new Function("a", "b", "alert(x);"); // this will not show x
tester(5, 10);
}
When you new up a Function, it does not automatically capture the current scope like declaring one would. If you were to simply declare and return a function, it will have closure:
function test(){
var x = 5;
tester = function (a, b) {
alert(x); // this will show x
};
tester(5, 10);
}
This is the trade-off you make for having dynamically compiled functions. You can have closure if you write the function in ahead of time or you can have a dynamic body but lose closure over the surrounding scope(s).
This caveat doesn't usually matter, but consider the (slightly contrived) case where you build a function body as a string, then pass it to a function constructor to actually be evaluated:
function addOne(x) {
return compile("return " + x + " + 1");
}
function addTwo(x) {
return compile("return " + x + " + 2");
}
function compile(str) {
return new Function(str);
}
Because the function is instantiated by compile, any closure would grab str rather than x. Since compile does not close over any other function, things get a bit weird and the function returned by compile will always hold a closure-reference to str (which could be awful for garbage collection).
Instead, to simplify all of this, the spec just makes a blanket rule that new Function does not have any closure.
You have to create an object to expose via return inside the test() function for it to be global. In other words, add var pub = {} and name your internal functions as properties and/or methods of pub (for example pub.tester = new func) then just before closing test() say return pub. So, that way it will be publically available (as test.tester). It's Called the Revealing Module Pattern.
What it means is that inside the function you can only refer to global variables, as you've found. However, the reference to the function itself is still in the local scope where it was created.
I'm confused as to where the confusion is.
It says that the function will be in global scope...and therefore will only have access to its own scope and the global scope, not variables local to the scope in which it was created.
You tested it and it has access to its own scope and the global scope, not variables local to the scope in which it was created.
So where's the confusion?
Is it in your assigning of the function to the variable testing? testing is just a local variable with a reference to the function...that has nothing to do with the scope of the creation of the function.
Scope is lexical, and has to do with where the function is created, not what random variables a function reference happens to be assigned to at runtime. And the documentation is telling you that when you make a function this way it acts as if it was created in the global scope...so it's acting completely as expected.
Here's an illustration:
This:
var y = 10;
var tester;
function test()
{
var x = 5;
// 10 and errors as not defined
tester = new Function("console.log(y); console.log(x);");
}
Is similar to this:
var y = 10;
var tester;
function test()
{
var x = 5;
// also 10 and errors as not defined
tester = something;
}
function something()
{
console.log(y);
console.log(x);
}
NOT
var y = 10;
var tester;
function test()
{
var x = 5;
// 10 and 5...since x is local to the function creation
tester = function()
{
console.log(y);
console.log(x);
}
}
From what i know, a function say A defined within another function say B has access to local variables of B as well.
function B() {
var x = 10;
function A() {
console.log(x); //will result in 10
var y = 5;
}
console.log(y); //ReferenceError: y is not defined
}
However in the below example y gets printed. I know there is no such thing as block scope in javascript for "if block" but shouldn a declaration atleast be invisible outside of "if" i mean shouldnt var y be limited to if block?
function B() {
var x = 10;
if(1) {
console.log(x); //will result in 10
var y = 5;
}
console.log(y); will result in 5
}
JavaScript isn't truly block scoped. An if or for loop does not have its own scope. All variable declarations in any given scope (that is: global scope, or a function) are hoisted, and this visible anywhere inside that scope.
ECMAScript6 (Harmony) will, in all likelihood, introduce block-scope to JS, through the use of the new let keyword see the wiki:
for (let i=0;i<12;++i)
{
console.log(i);//logs i
}
console.log(i);//reference error
There also seems to be some confusion as far as terminology is concerned here: a closure is not the same as a scope.
The snippet above is an example of block-scoped code. The variable i is created at the start of the loop, and simply ceases to exist once the loop finishes. It is GC'ed (Garbage Collected). i is no more, bereft of life it rests in peace. Closures are something different entirely: they rely on variables that are not GC'ed, but can't be accessed from outside code. They can only be accessed through the return value of the closure:
var someClosure = (function()
{//this function creates a scope
var x = 123;
return {
getX: function()
{
return x;
},
setX: function(val)
{
return x = val;
}
};
}());
console.log(x);//reference error
console.log(someClosure.getX());//returns 123, so "x" still exists
That being said:
You can mimic a block-scoped loop through the use of a closure, though. Functions are scoped, and a closure is a function or object that is returned by a function. That means that the return value of a function has access to the entire function's scope. See this answer for details.
Apply what is explained there, and work out why this loop is "pseudo-scoped":
var foo = [1,2,3,4,5,6],
largerThan3 = (function(arr)
{
var resultArr = [];
for (var i=0;i<arr.length;++i)
{
if (arr[i] > 3)
resultArr.push(arr[i]);
}
return resultArr;
}(foo));
console.log(i);//reference error...
nope.
as you said - if blocks does not have their own closures in JS - which means everything is part of the outer closure (in this case - y is a local variable in B's closure). so it will be completely visible in B's body
Hi still i'm not sure about the exact usage of using closures in javascript.I have idea about closures "A closure is an inner function that has access to the outer (enclosing) function’s variables—scope chain".But i don't know why we are using closures in javascript.
It allows you to succinctly express logic without needing to repeat yourself or supply a large number of parameters and arguments for a callback function.
There is more information available here: javascript closure advantages?
Imagine if instead of
alert("Two plus one equals" + (2+1) );
you'd be forced to declare a variable for every constant you ever use.
var Two = 2;
var One = 1;
var myString = "Two plus one equals";
alert(myAlert + (Two + One) );
You'd go crazy if you had to define a variable for every single constant before you can ever use it.
The access to local variables in case of closures is an advantage, but the primary role - usefulness - is the use of a function as a primary expression, a constant.
Take
function Div1OnClick()
{
Counter.clickCount ++;
}
$('#Div1').click(Div1OnClick);
versus
$('#Div1').click(function(){ Counter.clickCount++; });
You don't create a new function name in the "above" namespace just to use it once. The actual activity is right there where it's used - you don't need to chase it across the code to where it was written. You can use the actual function as a constant instead of first defining and naming it and then calling it by name, and while there are countless caveats, advantages and tricks connected to closures, that's the one property that sells them.
In general, the main use of closures is to create a function that captures the state from it's context. Consider that the function has the captured variables but they are not passed as parameters.
So, you can think of it of a way to create families of functions. For example if you need a series of function that only differ in one value, but you cannot pass that value as a parameter, you can create them with closures.
The Mozilla Developer Network has a good introduction to closures. It shows the following example:
function init() {
var name = "Mozilla";
function displayName() {
alert(name);
}
displayName();
}
init();
In this case the function displayName has captured the variable name. As it stand this example is not very useful, but you can consider the case where you return the function:
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Here the function makeFunc return the function displayName that has captured the variable name. Now that function can be called outside by assigning it to the variable myFunc.
To continue with this example consider now if the captured variable name were actually a parameter:
function makeFunc(name) {
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc("Mozilla");
myFunc();
Here you can see that makeFunc create a function that shows a message with the text passed as parameter. So it can create a whole family of function that vary only on the value of that variable ("Mozilla" in the example). Using this function we can show the message multiple times.
What is relevant here is that the value that will be shown in the massage has been encapsulated. We are protecting this value in a similar fashion a private field of a class hides a value in other languages.
This allows you to, for example, create a function that counts up:
function makeFunc(value) {
function displayName() {
alert(value);
value++;
}
return displayName;
}
var myFunc = makeFunc(0);
myFunc();
In this case, each time you call the function that is stored in myFunc you will get the next number, first 0, next 1, 2... and so on.
A more advanced example is the "Counter" "class" also from the Mozilla Developer Network. It demonstrates the module pattern:
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
alert(Counter.value()); /* Alerts 0 */
Counter.increment();
Counter.increment();
alert(Counter.value()); /* Alerts 2 */
Counter.decrement();
alert(Counter.value()); /* Alerts 1 */
Here you can see that Counter is an object that has a method increment that advances the privateCounter variable, and the method decrement that decrements it. It is possible to query the value of this variable by calling the method value.
The way this is archived is with an auto-invocation of an anonymous function that creates a hidden scope where the varialbe privateCounter is declared. Now this variable will only be accessible from the functions that capture its value.
Closures are a powerful construct used to implement a lot of additional features in JavaScript. For instance a closure can be used to expose private state as follows:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above example when we call getCounter we create a private variable count. Then we return a function which return count incremented. Hence the function we return is a closure in the sense that it closes over the variable count and allows you to access it even after count goes out of scope.
That's a lot of information stuffed in a few lines. Let's break it down?
Okay, so variables have a lifetime just like people do. They are born, they live and they die. The beginning scope marks the birth of a variable and the end of a scope marks the death of a variable.
JavaScript only has function scopes. Hence when you declare a variable inside a function it's hoisted to the beginning of the function (where it's born).
When you try to access a variable which is not declared you get a ReferenceError. However when you try to access a variable which is declared later on you get undefined. This is because declarations in JavaScript are hoisted.
function undeclared_variable() {
alert(x);
}
undeclared_variable();
When you try to access an undeclared variable you get a ReferenceError.
function undefined_variable() {
alert(x);
var x = "Hello World!";
}
undefined_variable();
When you try to access a variable which is declared later in the function you get undefined because only the declaration is hoisted. The definition comes later.
Coming back to scopes a variable dies when it goes out of scope (usually when the function within which the variable is declared ends).
For example the following program will give a ReferenceError because x is not declared in the global scope.
function helloworld() {
var x = "Hello World!";
}
helloworld();
alert(x);
Closures are interesting because they allow you to access a variable even when the function within which variable is declared ends. For example:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above program the variable count is defined in the function getCounter. Hence when a call to getCounter ends the variable count should die as well.
However it doesn't. This is because getCounter returns a function which accesses count. Hence as long as that function (counter) is alive the variable count will stay alive too.
In this case the function which is returned (counter) is called a closure because it closes over the variable count which is called the upvalue of counter.
Uses
Enough with the explanation. Why do we need closures anyway?
As I already mentioned before the main use of closures is to expose private state as is the case with the getCounter function.
Another common use case of closures is partial application. For instance:
function applyRight(func) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
var rest = Array.prototype.slice.call(arguments);
return func.apply(this, rest.concat(args));
};
}
function subtract(a, b) {
return a - b;
}
var decrement = applyRight(subtract, 1);
alert(decrement(1)); // 0
In the above program we had a function called subtract. We used partial application to create another function called decrement from this subtract function.
As you can see the decrement function is actually a closure which closes over the variables func and args.
That's pretty much all you need to know about closures.
It is because of information hiding.
var myModule = (function (){
var privateClass = function (){};
privateClass.prototype = {
help: function (){}
};
var publicClass = function (){
this._helper = new privateClass();
};
publicClass.prototype = {
doSomething: function (){
this._helper.help();
}
};
return {
publicClass: publicClass
};
})();
var instance = new myModule.publicClass();
instance.doSomething();
In javascript you don't have classes with ppp (public, protected, private) properties so you have to use closures to hide the information. On class level that would be very expensive, so the only thing you can do for better code quality to use closure on module level, and use private helper classes in that closure. So closure is for information hiding. It is not cheap, it cost resources (memory, cpu, etc..) so you have to use closures just in the proper places. So never use it on class level for information hiding, because it is too expensive for that.
Another usage to bind methods to instances by using callbacks.
Function.prototype.bind = function (context){
var callback = this;
return function (){
return callback.apply(context, arguments);
};
};
Typical usage of bound function is by asynchronous calls: defer, ajax, event listeners, etc...
var myClass = function (){
this.x = 10;
};
myClass.prototype.displayX = function (){
alert(this.x);
};
var instance = new myClass();
setTimeout(instance.displayX.bind(instance), 1000); //alerts "x" after 1 sec
I'm trying to create a function which returns another function. I want separate information when each of the inner function is run, but this isn't happening. I know that explanation is not great, so I've put together a small example.
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return that;
})(testVal);
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());
This outputs 2, 2. What I would like is 2, 4 to be output. I know this isn't explained perfectly, so if it's not clear what I'm trying to achieve, can someone explain why the variable seems to be shared across the two functions?
Thanks
Like this ?
var testFn = function(testVal) {
var test = testVal
return {
getVal: function() {
return test
}
}
};
var ab = testFn (4)
var ac = testFn (2)
console.log(ab.getVal(),ac.getVal()) //4 //2
The problem in your code is this.getVal() / returning this
because 'this' refers to the global scope / Window
You are glubbering with the global namespace and overwriting Window.getVal() , the moment you are setting b = testFn (2)
This results in overwriting as method getVal too because they both refer to the global Object and always share the same method getVal
Therefore they share the same closure and are outputing 2
console.log("The same: " + (Window.a === Window.b)) // true
console.log("The same: " + (a === b)) // true
you can see that if you change it a little:
var testFn = function(testVal) {
var x = {}
return (function(testVal) {
var test = testVal;
x.getVal = function () {
return test;
}
return x
})(testVal);
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());//4 2
it suddenly works because it results in 2 different Objects returned (btw you don't even need the outer closure)
console.log("The same: " + (a === b)) // false
Here are the JSbins First / Second
I hope you understand this, I'm not good in explaining things
If theres anything left unclear, post a comment and I'll try to update the answer
This question comes down to the context in which functions are invoked in JavaScript.
A function that is invoked within another function is executed in the context of the global scope.
In your example, where you have this code:
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
})(testVal);
}
The inner function is being called on the global scope, so this refers to the global object. In JavaScript a function executed within another function is done so with its scope set to the global scope, not the scope of the function it exists within. This tends to trip developers up a fair bit (or at least, it does me!).
For argument's sake, lets presume this is in a browser, so hence this refers to the window object. This is why you get 2 logged twice, because the second time this runs, this.getVal overwrites the getVal method that was defined when you ran var a = testFn(4);.
JavaScript scopes at function level, so every function has its own scope:
var x = 3;
function foo() {
var x = 2;
console.log(x);
};
console.log(x); //gives us 3
foo(); // logs 2
So what you want to do is run that inner function in the context of the testFn function, not in the global scope. You can run a function with a specific context using the call method. I also recorded a screencast on call and apply which discusses this in greater detail. The basic usage of call is:
function foo() {...}.call(this);
That executes foo in the context of this. So, the first step is to make sure your inner function is called in the right context, the context of the testFn method.
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
}.call(this, testVal);
}
The first parameter to call is the context, and any arguments following that are passed to the function as parameters. So now the inner function is being called in the right scope, it wont add getVal to the global scope, which is a step in the right direction :)
Next though you also need to make sure that every time you call testFn, you do so in a new scope, so you're not overwriting this.getVal when you call testFn for the second time. You can do this using the new keyword. This SO post on the new keyword is well worth reading. When you do var foo = new testFn() you create and execute a new instance of testFN, hereby creating a new scope. This SO question is also relevant.
All you now need to do is change your declaration of a and b to:
var a = new testFn(4);
var b = new testFn(2);
And now console.log(b.getVal(), a.getVal()); will give 2, 4 as desired.
I put a working example on JSBin which should help clear things up. Note how this example defines this.x globally and within the function, and see which ones get logged. Have a play with this and hopefully it might be of use.
The output you get is (2,2) because when you do
var that = this;
what you actually get is the global object (window),
the object that holds all the global methods and variables in your javascript code.
(Note that every variable that is not nested under an object or function is global and
every function that is not nested under an object is global, meaning that functions that are nested under a function are still global)
so, when you set:
var test = testVal;
this.getVal = function() {
return test;
}
you actually set the function "getVal" in the global object, and in the next run you will again set the same function - overriding the first.
To achieve the affect you wanted I would suggest creating and object and returning it in the inner function (as #Glutamat suggested before me):
var testFn = function(testVal) {
return new Object({
getVal: function() {
return testVal;
}
});
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());
In this way, in the outer function we create an object with an inner function called "getVal" that returns the variable passed to the outer function (testVal).
Here's a JSBin if you want to play around with it
(thanks to #Glutamat for introducing this site, I never heard of it and it's really cool :D)
Let's say I start up a var for an Object in my code
var base = {x:Infinity, y:Infinity};
and later in the same scope I do
var base = {x:0, y:0}
I get that I can re-use the existing variable, but I'm trying to iterate on a point.
Does this cause any problems for the current scope as far as memory is concerned?
Would there be any problems if these are in different scopes?
Is the general rule to never use var on an already-existing variable?
If I did this several (thousands) of times, would I run into any "funky" issues?
It releases its hold on the old value, so it can be potentially garbage collected. I say potentially, because objects can be referenced by different variables.
If they're in different scopes, the inner base will shadow the outer one (assuming you're talking about nested scopes), so the old value will not be overwritten. Shadowing is usually best avoided.
Generally, within the same scope, yes but that's more of a coding style aspect. It won't make an effective difference in the execution since there's only one declaration no matter how many times you declare the same var in the same scope.
Depends. Are you talking about overwriting in a loop? If you no longer need the current value, it shouldn't be an issue.
To be clear, when you do this:
var base = {x:Infinity, y:Infinity};
var base = {x:0, y:0}
What's really happening is this:
var base; // declaration is hoisted
base = {x:Infinity, y:Infinity}; // new object is referenced by base
base = {x:0, y:0} // previous object is released, and new object is referenced
Note that when I talk about scope and var, I'm talking specifically about function scope. In standard JavaScript/ECMAScript implementations, there is no block scope, so there's no special meaning when using var in a for statement for example.
As mentioned by #Charles Bailey, Mozilla has let, which does allow scoping in blocks, but it would require that specific keyword. The var statement doesn't recognize the block with respect to variable scope.
There is absolutely no problem in doing that. Afterall, variables declared within a function (-context) are just part of the such called Activation Object (ES edition 3). It is a little bit different in ES5, but for this part it is basically the same.
You are just overwritting a property, in an Object (not a Javascript object, but from the underlaying js engine).
So again, that is not a problem at all (even if its unusual und looks confusing).
If you declare a variable in another "scope" (which basically means, another function here), it is also no problem. Each (execution) context is completely on its own and cannot interfer with another context, unless we are talking about closures and stuff. But even then, if you have several functions and parent context which all have the same named variable, the lookup process (name resolution) always begins in your local scope (the Activation object from the current context) and after that, it goes into the "scope chain".
I guess that should answer 3.) and 4.) also. You "can" re-var a variable, but it makes no sense. So I'd just recommend to don't do it anymore.
The var keyword provides scope to a variable. The only scope available to JavaScript at this time is function scope. If the variable is already scoped to this function then setting with the var keyword again does nothing.
JavaScript is lambda language, which means variables declared in a higher scope are available to functions inside that higher scope. Providing a variable from a higher scope with the var keyword in a lower function scope could be harmful, because you have now created a local variable that may be intended as closure. Consider the following two examples:
var a = function () {
var b = 3,
c = function () {
var d = 5;
b = 5;
return d + b; // this is 10
};
return c() + b; // this is 10 + 5, or 15
};
var a = function () {
var b = 3,
c = function () {
var b = 5,
d = 5;
return d + b; // this is 10
};
return c() + b; // this is 10 + 3, or 13
};
I said unintentionally altering variable scope is potentially harmful, because it will confuse how your code works from how you think it should work.
The general rule is one var declaration per function, and that var declaration belongs at the top of the function:
function foo() {
var bar;
}
The reason to do it is to avoid confusion that could be caused by variable hoisting.
An example of where this matters is with closure context for callbacks:
//this looks like it will count up, but it wont
function foo() {
var i;
for (i = 0; i < 10; i++) {
var bar = i;
setTimeout( function () {
console.log(bar);
}, 1000 * i);
}
}
//this is actually what's happening behind the scenes
//hopefully you can see why it wont work
function foo() {
var i, bar;
for (i = 0; i < 10; i++) {
bar = i; //bar is in the same scope as i
setTimeout( function () {
//when this is called `i` and `bar` will both have a value of 9
console.log(bar);
}, 1000 * i);
}
}
If you've got a sub-function, you can declare a new variable of the same name, which will remain for the scope of that sub-function:
function foo() {
var bar;
function baz() {
bar = 2;
}
bar = 1;
baz();
console.log(bar); //output will be 2 because baz operated in the outer scope
}
function foo() {
var bar;
function baz() {
var bar;
bar = 2;
}
bar = 1;
baz();
console.log(bar); //output will stay 1 because baz operated in its own scope
}
If your example code is along the lines of:
function foo() {
var base = {x:Infinity, y:Infinity};
...some code...
var base = {x:0, y:0};
}
It will actually execute as:
function foo() {
var base;
base = {x:Infinity, y:Infinity};
...some code...
base = {x:0, y:0};
}