i'm a beginner in javascript and i tried to learn about function that called inside a function which redefine a value of a variable. Here's the code
var a;
function app2(a) {
var a = 8;
return a
}
function app(a) {
var a = 7;
app2(a)
return a
}
console.log(app(a));
when i run code, it still show 7 as the output. i thought it will be 8 because i've called the function app2 in the app function. why the value doesn't change into 8? and what should i do update the variable value inside the nested function? thanks in advance
1) You can only get 8 if you are taking the value of app2 and using it inside app.
Variables declare with var keyword are function scoped and they are not visible outside of that particular function in which it is declared.
a declared in app2 is not visible inside app unless you are not returning the value from app2 and not using the return value from app2 inside app(Both condition should be satisfied to use it)
var a;
function app2(a) {
var a = 8;
return a;
}
function app(a) {
var a = 7;
a = app2(a); // reassign the returned value from app2
return a;
}
console.log(app(a));
2) If you are returning it and not capturing it, then It's no use. You can also do as:
var a;
function app2(a) {
var a = 8;
return a;
}
function app(a) {
var a = 7;
return app2(a); // Directly return the value of app2 returned value
}
console.log(app(a));
I think the main culprit of what you are seeing is that you are naming the arguments of the functions a and also the global is named a.
When experimenting with this you would expect a = 8 when all var keywords are removed except for the global one. This does not happen because the argument, named a, is shadowing the global var a. When you use the var keyword locally in a function you are essentially telling javascript you want to declare a local function-scoped var a, and not reference the global var a, so this way any changes stay in the function scope.
Check this snippet out:
var a;
function app2(b) { // changed argument name from `a` to `b`
a = 8; // removed var keyword here
return a
}
function app(b) { // changed argument name from `a` to `b`
a = 7; // removed var keyword here
app2(a)
return a
}
console.log(app(a)); // output: 8
Related
function makeMultiplier (multiplier){
var myFunc = function (x){
return multiplier * x;
}
return myFunc;
}
var multiplyBy3 = makeMultiplier(3);
console.log(makeMultiplier(3)(10));
Here, I don't understand why and how does the var multiplyBy3 variable acts as a reference to the myFunc function mentioned above
The return value of executing the function makeMultiplier is function myFunc. This is being assigned to variable multiplyBy3 . Hence it will act as a reference to myFunc function
Order of execution:
makeMultiplier is defined
makeMultiplier is called with arg 3 and returns a new function and that returned function is stored in a variable named multiplyBy3.
console log called with makeMultiplier is called with 3, returns a new function and it is called with argument 10
In JavaScript all the non primitive objects' assignments are stored as reference, but not as value. Example variable assignments, argument passing to functions where it basically assigned to the parameter which is a local variable inside the function.
However, second call to the multiplier with arg 3 is a different function, the references are different.
Also you can test those with Object.is() static method.
In your code, you don't actually use multiplyBy3, but here's your code modified to use it as the reference to the inner myFunc(3):
function makeMultiplier(multiplier) {
var myFunc = function(x) {
return multiplier * x;
}
return myFunc;
}
var multiplyBy3 = makeMultiplier(3);
console.log(multiplyBy3(10));
When setting the multiplyBy3 variable, we call the makeMultiplier function with 3 as our multiplier argument. This returns a reference to function(x) { return 3 * x; } which is assigned to multiplyBy3.
Calling multiplyBy3(10) then results in the value of 30 due to multiplying 3 by the argument of 10. This is equivalent to your original code makeMultiplier(3)(10)
In the following code snippet, I modified your code to use multiplyBy3 and threw in some console.log statements to show the steps taken both outside and inside the functions.
function makeMultiplier(multiplier) {
console.log("[enter] makeMultiplier");
var myFunc = function(x) {
console.log("[enter] myFunc");
return multiplier * x;
}
return myFunc;
}
console.log("[before] 'var multiplyBy3 = makeMultiplier(3);'");
var multiplyBy3 = makeMultiplier(3);
console.log("[after] 'var multiplyBy3 = makeMultiplier(3);'");
console.log("[before] 'console.log(multiplyBy3(10));'");
console.log(multiplyBy3(10));
console.log("[after] 'console.log(multiplyBy3(10));'");
Additionally, I'll show an alternate example where we multiply by 4:
function makeMultiplier(multiplier) {
console.log("[enter] makeMultiplier");
var myFunc = function(x) {
console.log("[enter] myFunc");
return multiplier * x;
}
return myFunc;
}
console.log("[before] 'var multiplyBy4 = makeMultiplier(4);'");
var multiplyBy4 = makeMultiplier(4);
console.log("[after] 'var multiplyBy4 = makeMultiplier(4);'");
console.log("[before] 'console.log(multiplyBy4(10));'");
console.log(multiplyBy4(10));
console.log("[after] 'console.log(multiplyBy4(10));'");
I have a function that returns a variable and a function which edit the variable value.
But it's not working and I don't know why.
And what is the correct way to do this?
Here is my code:
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
The value of test is a primitive and so it is indeed not a reference.
A solution: make the exposed test property a getter, so that the value of the private test variable is retrieved at the moment the property is accessed:
return {
changeTest:changeTest,
get test() { return test }
}
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest,
get test() { return test }
}
}
var b = t();
b.changeTest();
console.log(b.test);
With this pattern, the test variable remains private, and you only expose the features you want to. So in this case you allow explicitly to read the test value, but not to write it.
NB: you can shorten the object literal notation to just:
return {
changeTest,
get test() { return test }
}
In changeTest you have to use this.test instead of test.
function t(){
var test = 1;
var changeTest = function(){
this.test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
If you would like to increase inside of the function, you need to use this keyword inside, just like the following:
function t(){
const changeTest = function() { this.test++; };
return { changeTest, test: 1 };
}
const b = t();
console.log('original value', b.test);
b.changeTest();
console.log('increased value', b.test);
The reason is why it is happening because you are not modifying the value inside, it is called lexical closure what you face with, as the documentations states:
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
Using the this keyword the code accesses the proper test variable.
For further explanation please read further here:
Closures: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
I hope this helps!
Any function within function forms a closure. Do closures always needs to be in an immediately invoked function?
The first example is where a closure is formed within an iife and works as expected, gives "8" and "7" as output.
var cat = (function (){
var lives = 9;
return function() {
return --lives;
}
}());
console.log("iife");
console.log(cat());
console.log(cat());
In the below example the closure does not work as expected, prints the same value every time.
var cat = function (){
var lives = 9;
return function() {
return --lives;
}
};
console.log("no iife");
console.log(cat()());
console.log(cat()());
A closure is just the link between a function and the scope in which it was created, link which exists when the function uses a variable from this scope.
You have this problem because you don't keep the closure: you're recreating it at every console.log when you call cat().
Change
console.log(cat()());
console.log(cat()());
into
let c = cat();
console.log(c());
console.log(c());
I am trying to understand closures.
var a = 1;
var g = function () {
var a = a;
return function() {
console.log(a);
}
}
g()();
As far as I know, the function invocation g()() should log the value of a, i.e. 1. But it is logging undefined on the console. I know my concept is weak somewhere, but am not able to figure out even after spending few hours. Can someone help?
JavaScript hoists var declaration in the entire function scope. The variable from the outer scope var a = 1 is overwritten.
The example is equivalent to this:
var a = 1;
var g = function () {
var a; // a is undefined
a = a; // a = undefined
return function() {
console.log(a);
}
}
g()();
Without initial value assignment, a is simply undefined. Later you assign the variable to itself a = a, which is a noop and a remains undefined.
For more information about variables hoisting, check this article.
The problem is the line
var a = a;
This is both declaring a locally scoped variable and assigning it to itself - it's not interacting with the global a. You need to use a differently named local variable:
var a = 1;
var g = function() {
var b = a;
return function() {
console.log(b);
}
}
g()();
function emergency() {
var ambulance = 100;
var callAmbulance = function() { alert(ambulance); }
ambulance++;
return callAmbulance;
}
var accident = emergency();
accident(); // alerts 101
I am referring to the variable 'ambulance'.
When I call accident(); it should call emergency() which should use the declared variable 'ambulance' [considering the global scope thing in javascript, still it could set the value to global] but its using old value 101 instead of setting again back to 100 - behaving more like static var.
What's the Explanation?
What you have there is called a closure. It means a function can access variables declared in outer functions (or in the global scope). It retains access even after the 'parent' function has returned. What you need to understand is that you don't get a copy. The changes performed on that variable are visible to your inner function, which in theory means you could have multiple functions sharing access to the same variable.
function f () {
var x = 0;
function a() { x += 1; }
function b() { x += 2; }
function show() { console.log(x); }
return {a:a, b:b, show:show};
}
var funcs = f();
funcs.a();
funcs.b();
funcs.show(); // 3
One thing to be aware of is that a subsequent call to f will create a new scope. This means a new x variable will be created (new a, b, show functions will be created as well).
var newFuncs = f();
newFuncs.a();
newFuncs.show(); // 1
funcs.a();
funcs.show(); // 4
So, how do you get a copy? Create a new scope.
function g () {
var x = 0;
var a;
(function (myLocal) {
a = function () { myLocal += 1; }
}(x));
x += 200;
return a;
}
JS only has pass-by-value so when you call the anonymous function, the xvariable's value will be copied into the myLocal parameter. Since a will always use the myLocal variable, not x, you can be certain that changes performed on the x variable will not affect your a function.
If, by any chance, you're coming from a PHP background you are probably used to do something like
use (&$message)
to allow modifications to be reflected in your function. In JS, this is happening by default.
You are creating a function definition which is not compiled at this time:
var callAmbulance = function() { alert(ambulance); }
And before you are sending it to the called function, you are incrementing the num:
ambulance++;
And then you are sending it to the called function:
return callAmbulance;
But whether you are sending it there or not, it doesn't matter. The below statement executes or compiles the function:
var accident = emergency();
And this takes in the current ambulance value which is 101 after the increment. This is an expected behaviour in creating function but not executing it. Please let me know, if you didn't understand this behaviour. I will explain it more clearly.