i have a global variable x, which has the same name as that of the inner function
when i execute the test function it also executes the function which has same as that of the global variable, this function contains assigns value to the variable which has the same name as that of the function, now when in the next line it alerts the value of the x, it alerts 2, but when after the execution of the test function if you alert the x it still alerts 10... y?
eg
var x =10; //assigns value 10 to global variable x
function test(){
function x () {
x = 2; //assigns value x
alert(x); // x =2
}
x(); //calls x
}
test(); //call function test
but if you alert x, then it gives 10...
why like this;
and if you do like this
var y =10; //assign value 10 to y
function test(){
function x () {
y = 2; //assign value 2 to y
alert(y); //alerts y is 2
}
x(); //call the function x
}
test(); //call the test function
and if you check y then also it is 2..
what is the difference between the two.. I know the behaviour of the second one..
but have no idea about the first one...
A function declaration does two things:
It declares a new variable in the current scope (with the same name as the function). This is the same as var x.
It creates a function and assigns it to that variable. This is the same as x = function x () { ... } except it is hoisted.
In the first example, the function declaration for x creates a variable x in the scope of test so when you x = 2;, you are overwriting the pointer to the function in x with 2 while leaving the other variable x (which exists in the wider scope and holds the variable 10 alone).
This can be demonstrated:
var x = 10;
function test() {
function x() {
x = 2; //assigns value x
}
alert("x inside test before calling x(): " + x)
x(); //calls x
alert("x inside test after calling x(): " + x)
}
alert("x outside test before calling test(): " + x)
test()
alert("x outside test after calling test(): " + x)
In the second example, the function is called y, so it doesn't create a new x in the narrower scope and x = 2 touches the original x.
The function keyword is similar to var -- they both make the name they define into a local variable. So there are two x variables: one whose scope is outside the test function, the other whose scope is inside the function. Assigning to the inner x has no effect on the outer x.
In your second version, you don't have a var or function declaration for y inside the function, so it accesses the global variable.
For more information, see
What is the scope of variables in JavaScript?
Related
This question already has answers here:
typeof of a function not returning correct value but undefined
(2 answers)
Closed 4 years ago.
The example below must output for sure function, as the value of x is "1" (integer) and then we are passing a parameter named "f" (of a function). It doesn't matter whether this function does something or is blank, but I am sure -- that variable f --> points to function. so typeof(f) will surely return function.
Now, adding of an integer and "function" (as typeof always returns a string) is going to be a string --> 1function.
Now, amazingly the output is "1undefined". How?
<script>
var x = 1;
if (function f(){}) {
x += typeof f;
}
console.log(x);
</script>
As per answer by Ellepsis that declarations don't take inside if() braces and only boolean is returned. Explain this then, why is it returning 3?
<script>
var x = 1;
if (y = 2) {
x = x + y;
}
console.log(x);
</script>
if (function f(){}) {
A function declaration will create a variable with the same name in the current scope.
A function expression will only create a variable with the same name inside itself.
So the variable f only exists:
if (function f(){ })
^^^^
here
The function expression itself evaluates as a function, which the if statement picks up as a truthy value but there is no f variable in scope.
Explain this then, why is it returning 3?
You are explicitly assigning a value to a variable. That variable remains in scope.
You would get the same effect if you did this:
if (f = function f(){}) {
So:
(function f(){})
Creates a function
Names the function f
Creates a variable inside the function called f containing a reference to a function
Evaluates as a function, which is a true value, which is tested by the if
While:
(f = function f(){})
Creates a function
Names the function f
Creates a variable inside the function called f containing a reference to a function
Creates a variable f outside the function
function f(){} evaluates as a function and is assigned to f by the =
f = function f(){} also evaluates as a function, which is a true value, which is tested by the if
You are getting undefined because function f is not defined in the code anywhere. Writing the function inside an if statement does not define the function. The code just assumes it as a truthy value, a condition for the if statement but in real f does not exists. You can define f outside and it will work fine or you can just perform the assignment in the if and then also it will work
var x = 1;
if (f=function(){}) {
x += typeof f;
}
console.log(x);
var x = 1;
var f;
if ( f = function() {} ) {
x += typeof f;
}
console.log(x);
I have following js code.
var a = (function(){
var x = 0;
var y = function(){
x++;
console.log(x);
}
var z = function(){
return x;
}
return {
x, y, z
}
})();
Here when I try to access a.x for the first time, It is giving me output 0(which is expected as x is initialized to 0), Then I am incrementing the value of x using function y. But after incrementing value of x two times(or maybe more then 2), when I try to access the value of x it is stll giving me a.x=0. I am not able to understand why it is happening as I already change the value of x using function y. Then why it is not changing.
(But when I am accessing value of x through some function it is giving incremented value. Why this different behavior. if the same variable I am directly access then it will give some output and when the same variable value I am returning through some function it is giving some other value. Why?)
var a = (function(){
var x = 0;
var y = function(){
x++;
console.log(x);
}
var z = function(){
return x;
}
return {
x, y, z
}
})();
console.log(a.x);
a.y();
a.y();
console.log(a.x);
console.log(a.z());
I guess it is because of closure but not sure about it.
The last line:
return { x, y, z };
is the same as:
return { x: x, y: y, z: z };
So it copies the local variables into the object. For functions or objects that doesn't matter as they are copied by reference, primitives however are copied by value, therefore you got two different z, a local variable and the object property.
When you create an object and return it:
return {
x, y, z
}
The x property in the object receives a copy of the local variable x. It is not bound in any way to the local variable other than that, so subsequent changes to the variable in the closure are not reflected in that object.
You could make a getter:
return {
get x() { return x; },
y, z
};
That will cause any access to the "x" property of the returned object fetch the current value of x in the closure.
I'd like to understand the debugging content during the execution of the following code:
var z = 2;
var SQUAREPLUSOTHER = x => y => ((x*x) + y + z);
var x = 3;
console.log("SQUAREPLUSOTHER", SQUAREPLUSOTHER);
var squareoftwoplusother = (SQUAREPLUSOTHER)(x);
x = 4;
z = 4;
var result = squareoftwoplusother(5);
console.log("result", result);
Now....
At the call of:
console.log("SQUAREPLUSOTHER", SQUAREPLUSOTHER);
the debug shows clearly:
squareoftwoplusother: undefined
SQUAREPLUSOTHER: x=>...
x: 3
z: 2
at the following call of:
var SQUAREPLUSOTHER = x => y => ((x*x) + y + z);
the debug shows:
Local:
x: 3
Closure
z: 2
at the following call of:
x = 4;
z = 4;
the debug shows:
squareoftwoplusother: y=>...
SQUAREPLUSOTHER: x=>...
x: 4
z: 4
at the following call of:
var result = squareoftwoplusother(5);
the debug shows:
result: 18
squareoftwoplusother: y=>...
SQUAREPLUSOTHER: x=>...
Local:
x: 5
Closure
x: 3
Closure
z: 4
and at the final calls the debug shows:
result: 18
squareoftwoplusother: y=>...
SQUAREPLUSOTHER: x=>...
x: 4
z: 4
now the questions:
How many "Closures"? They belongs to? (i.e. how to explain...)
Local:
x: 5
Closure
x: 3
Closure
z: 4
How the scope of the variables is managed in javascript?
How to have a "definitive" idea in terms of "context" or "whatever it be" about the mess of closure :-)?
thanks in advance
Ed
Every time a function is called, a local scope is created for that function. If there is still a reference to that local scope after the function returns, then a closure is created. Once the reference is gone, the closure is also garbage collected.
If you add breakpoints to the first line of every function, you will see that scopes are created that may later become closures.
A great explanation is given here http://dmitrysoshnikov.com/ecmascript/javascript-the-core/#activation-object
I'll add some braces to your code to make that easier and I'll add self calling function to add a level of closures.
(() => {
var z = 2;
var SQUAREPLUSOTHER = (x) => {
debugger;
return (y) => {
debugger;
return (x * x) + y + z;
}
};
var x = 3;
console.log("SQUAREPLUSOTHER", SQUAREPLUSOTHER);
var squareoftwoplusother = (SQUAREPLUSOTHER)(x);
x = 4;
z = 4;
var result = squareoftwoplusother(5);
console.log("result", result);
debugger
})()
The screenshots below are from Chrome DevTools which minimizes the closures, that is, it only maintains references to what is needed. Back in the days, the entire closure was always available and you could prove it because it showed up in the closures pane of debuggers. See Javascript closures performance for further details
Scope
There are just three different scopes in your code. One is the global scope all variables you declare in and the other two are here:
var SQUAREPLUSOTHER = x => y => ((x*x) + y + z);
There are two function scopes, one containing the variable x and the other function scope containing the variable y. It might be easier to see if you replace the arrow function with functions:
// global scope
function SQUAREPLUSOTHER(x) {
// function scope containing x
return function(y) {
// function scope containing y
return (x*x) + y + z;
};
}
How scoping works is actually quite simple:
Every { starts a new scope and its counter } closes it, variables declared inside it with let and const (or var but thats slightly more complicated) are part of the scope. If it is the scope of a function, the parameters (e.g. x and y) are part of that scope.
From the code, you can access the all variables that are in the current scope or in its parent scope, if there are multiple with the same name you get the most inner one. Therefore x inside of the SQUAREPLUSOTHER function refers to the variable of the SQUAREPLUSOTHER scope, while for code outside of it x is the global variable and the functions variable can't be accessed.
The Scope of a variable does not change at runtime, you can always directly see which scope a variable belongs tp by looking at the surrounding { .. }.
Now different variables in different scopes have to hold values at runtime, thats where we get to:
the environment record
When you call a function, the JavaScript engine creates a new "EnvironmentRecord" (which is like an internal object) that contains all the variables of the function you call, e.g. in this case:
function test(a) {
let b;
}
Then if you call that function (test(1)) a new environment record gets created that contains a and b. Now the code inside the function gets run, and every variable is looked up in it. If there are two functions nested into another, calling the inner function will create an environment record that holds a reference to the outer one:
function test(a) {
function test2(b) {
}
test2(5);
}
Now calling test(1) will create an record where a is 1. If the engine then executes the second call (test2(5)) it creates another record containing b being 5, and that holds a reference to the record containing a. Now if you use a inside test2, the engine will look it up in the current environment record, won't find it, and then look it up in the parent where it finds a being 1.
closure
Usually those records get deleted when the execution reaches the }, however if there is another record that got the current record as a parent, it won't get deleted. It will exist until all child records got deleted, then it will also remove the parent. This behaviour (variables live longer because they can be accessed from an inner functions body) is called a closure.
This question already has answers here:
Does JavaScript pass by reference? [duplicate]
(13 answers)
Closed 7 years ago.
Why doesn't this work and is there any way to get it to work?
Im pretty sure it doesn't work because of variable scoping in javascript, but I can't think of any ways to get it to work.
Code
var x = 5;
var z = function(y) { y = 10; };
z(x);
console.log(x) // Outputs 5 instead of 10
var x = 5
var z = function(y) { y = 10; }
console.log(x) // Outputs 5 instead of 10
Where exactly did you changed X? you dont have X and you did not call the function as well.
I assume you wish to do this:
var x = {x: 5}
var z = function(y) { y.x = 10; }
z(x);
console.log(x.x) // Outputs 10
The code is using x as variable on an object instead of a primitive number which is passed by value and not by reference and thus cannot be modified.
Using object you can modify the attributes (properties) of the object
X won't change for a couple reasons. The first is that you are modifying the parameter y inside of the function. If you passed an object this would work as those are passes by reference. It would also work if you changed x directly instead of passing it as an argument.
The second reason is that you never ran the function. You need to call z with z()
What happens when you invoke the function z is that the parameters get initialized and assigned the value you passed in.
So the function might read something like
var y = 5;
y = 10;
and so, the y that is in the scope outside of the function, remains unchanged because this y is actually a whole new y variable just for this function's scope.
var x = 5;
var z = function(y)
{
y = 10;
//assigned value 10 to the function parameter variable y.
//You haven't done x=y or x=10 and so how do you expect the value of x to change?
}
console.log(x) // Outputs 5 instead of 10
Change it to:
var x = 5 ;
var z = function(y)
{
x = 10; //changed value of x to 10
}
console.log(x) // Outputs 10
The problem is not related to vatiable scope at all.Your variable x is global since it is outside the function.
AND YES,you can change it's value inside a function.But the problem with your code was that you never changed the value of x.
If this is what you intended to do:
z(x); //x=5 is passed to the function z
function(y)
{
y=10; //initially the value of y is 5.Since you have passed x.
//Doing y=10 does not change the value of x because y is another variable.The value of x was copied to y and y is not x.
x=y;//You have assigned 10 to x
}
console.log(x); //outputs 10
Changing the value of the function parameter does not change the value of the variable whose value you passed to the function.You are actually passing the value of x to y that is you are passing 5 to y and not the variable itself.
You are not passing the variable reference.You are just passing the value.
I am looking at this function
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp));
}
}
var bar = foo(2); // bar is now a closure.
bar(10);
when I run it, the variables get the following values
x = 2,
y = 10
tmp = 3.
Now I see that in foo(2) x is passed as 2. So its understandable that x is getting the value of 2. But then bar(10) is assigning a value of 0 to y. Hows that? I am confused on how does the receiving function know that 10 is the value for y assigned by bar(10)
foo(2) returns an anonymous function which accepts one parameter (y). As you're setting bar to be the return value of foo(2), bar becomes a reference to that anonymous function.
So, when you call bar(10) you're calling the anonymous function foo returns, and so 10 is being set to the parameter y.
This is a closure.
When you write:
var bar = foo(2);
it's actually calling foo, so the net result is:
var bar = function (y) {
alert(2 + y + (++tmp));
}
where tmp is the value bound in scope by the closure.
So, subsequently calling:
bar(10);
is passing 10 into that function, with the result being:
alert(2 + 10 + (++tmp));
tmp will increase each time you call any function created with foo