Javascript immediate function and code scope - javascript

I am confused about scope when comparing normal function and immediate function.
Here is a example:
var num=5;
var x=3;
doubleNum = function(){
num = num*x
x++;
return num;
};
console.log(doubleNum());//15
console.log(doubleNum());//60
console.log(doubleNum());//300
This is a normal function that num and x are defined globally and accessible by doubleNum, as a result num and x are updated.
var num=5;
var x=3;
doubleNum = function(){
num = num*x
x++;
return num;
}();
console.log(doubleNum);//15
console.log(doubleNum);//15
console.log(doubleNum);//15
However if I define a immediate function and call it same way as above, I got different answer. Even I am expecting to have same output
Did I miss something essential? Or did I understand some concept wrong?
Please help.
Thanks in advance.
Jsfiddle

Because your doubleNum is not a reference to the function, but keeps the result of an anonymous function call.
In the first case you assign to the doubleNum a function and every time calling it via doubleNum(), you change the outscoped variables inside it and return a num. You do this 3 times. Your code is equivalent something to like
var num=5;
var x=3;
doubleNum = function(){
num = num*x; // Every call will affect the outscoped num
x++; // Every call will affect the outscoped x
return num;
};
var val = doubleNum(); // Call changes the values and returs a new result
console.log(val);
val = doubleNum(); // Call changes the values and returs a new result
console.log(val);
val = doubleNum(); // Call changes the values and returs a new result
console.log(val);
In the second case you assign to the doubleNum the result of a single call anonymous function. The function value is already computed one time and assigns the result to the doubleNum. Your code is equivalent something to
var num=5;
var x=3;
var doubleNum;
var myFunction = function(){
num = num*x;
x++;
return num;
};
doubleNum = myFunction(); // Only one call
console.log(doubleNum);
console.log(doubleNum);
console.log(doubleNum);

Did I miss something essential?
Just that in the second case, the value of doubleNum is already computed because the function is invoked as soon as it is defined.
On the other hand, in the first case only function definition was assigned to doubleNum rather than the result of its invocation.

The immediate function call is being evaluated only once. You're allocating a value not an immediate function to doubleNum. To accomplish a similar effect, try using a class and getters.
class ClassName {
constructor(){
this.num = 5;
this.x = 3;
}
get doubleNum() {
this.num = this.num*this.x++;
return this.num;
}
}
var double = new ClassName();
console.log(double.doubleNum);//15
console.log(double.doubleNum);//30
console.log(double.doubleNum);//300

Related

What does function in function do exactly in nodejs?

See this example:
var tools1 = require('../tools/tools1');
var test_func = function(arg1, arg2, arg3) {
var local_var_1 = "lc1";
var local_var_2 = "lc2";
return function(data) {
var result = tools1.doSth(local_var_1);
result = result+local_var_2;
}
}
exports.test_func = test_func;
I do not understand what does inner function do what it is for!
In javascript when you return function it returns reference of that function and you can call it later.
In your Code when you do var result = test_func(), result will hold reference of that function. Then later you can call that returned function like result(data).
A basic example:
function sum(x, y) {
var rs = x+y;
return function(message) {
console.log(message + rs); //rs holds its value because of clousers
}
}
var result = sum(2, 3);
result("This is result: ");
Variables that are used locally, but defined in an enclosing scope
like rs in above example because of Closures
This concept of function inside a function is known as closure in JavaScript. They are self invoking and makes it possible to have a function's private variables.
I am representing a similiar code of yours which I found in W3schools.com.
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
Initially, the counter is set to 0 and then it returns a function reference. The counter is protected by the scope of the anonymous function, and can only be changed using the add() function.
The counter is set to 3 then, as add() function is called three times.
In the very similiar way, your code is working I guess:
var test_func = function(arg1, arg2, arg3) {
var local_var_1 = "lc1";
var local_var_2 = "lc2";
return function(data) {
var result = tools1.doSth(local_var_1);
result = result+local_var_2;
}
}
the local_var_1 and local_var_2 is set to "lc1' and "lc2" and returning a function reference.
The inner function then comes and do some operation with tools1.doSth() on local_var_1 and append the result with local_var_2.
Note: I am not clear with the output of your code, so I tried to tell you the steps with help of another code.

Why does this function not return the variable after evaluating it?

Can somebody explain to me why a is not 8. I know that a = 7 after the code has run, but how do I make the function return so that it will be 8 ? New at java Script.
Can anybody explain this to me ?
var a = 5;
function foo(a)
{
a++;
}
a += 2;
console.log(a);
Firstly, you create a function, but you don't call it. It won't run automatically, the way you created it.
As someone mentioned, you have 2 different 'a' variables. One exists inside the function, and one outside. Consider them to be two completely different things.
var a = 5;
function foo(a)
{
a++; //This adds just 1 to a. If you want to add more, you can do a = a + 2; or whatever
return a; //Whenever you call this function, it will return a
}
a = foo(a); //Take the current a (which is 5) pass it to foo(). Assign the resulting returned value to a.
a += 2; //add 2 to a.
console.log(a);
That code will yield an a = 8. Starts at 5, adds 1, adds 2.
Working jsfiddle: http://jsfiddle.net/revg819p/1/
Your function foo(a) is not executed. And your code is semantically equal to:
var a = 5;
a += 2;
console.log(a);
function foo(a) {
a++;
}
Moreover, calling function foo(a) won't change the state of global variable a

When defining a function, why do I need to return a function instead of returning the value I want straightaway?

I'm new to the concept of nesting a function within another function and I don't understand the need for returning a function instead of returning the value I want straightaway..
Appreciate any help in clearing my confusion!
1st method (What I would have instinctively written, but turned out to be wrong):
function wrapValue(n) {
var localVariable = n;
return localVariable;
}
var wrap1 = wrapValue(1);
var wrap2 = wrapValue(2);
console.log(wrap1());
console.log(wrap2());
// → Uncaught TypeError: number is not a function
I tried a simpler version of method 1 which works (method 1.1):
function wrapValue(n) {
var localVariable = n;
return localVariable;
}
console.log(wrapValue(6));
// → 6
2nd method (the correct method):
function wrapValue(n) {
var localVariable = n;
return function() {
return localVariable;
};
}
var wrap1 = wrapValue(1);
var wrap2 = wrapValue(2);
console.log(wrap1());
console.log(wrap2());
// → 1
// → 2
Why does method 1 not work when method 1.1 works? And why the need for method 2?
Thanks for the help!
Why does method 1 not work when method 1.1 works?
Because in method 1, you're trying to call the value you got back from wrapValue as though it were a function, but it isn't; it's a number (the number you passed in). In Method 1.1, you're using the return value directly, you're not trying to call it as though it were a function.
Let's break it down a bit:
var wrap1 = wrapValue(1);
Now, in wrap1, we have the number 1. Not a function, just the number. So to use the number, we'd just use it directly:
console.log(wrap1); // 1
You can't call wrap1 because the variable doesn't refer to a function, it contains a number.
And why the need for method 2?
You only need method 2 if you have some reason that you need the access to localVariable to happen when you call the function wrapValue returns. Here's an example showing how that might change:
function doSomething(n) {
var num = n;
return function() {
++num;
return num;
};
}
var f = doSomething(0);
console.log(f()); // 1
console.log(f()); // 2
console.log(f()); // 3
Because calling the function doSomething returns changes the value of the num variable, we want to get the latest version each time we call it.
There I used a local variable to make it similar to your original example, but we could just use n directly:
function doSomething(n) {
return function() {
++n;
return n;
};
}
var f = doSomething(0);
console.log(f()); // 1
console.log(f()); // 2
console.log(f()); // 3
Function arguments are effectively local variables in the function. (Effectively, not literally.)
You have an error in your first function, it should be:
function wrapValue(n) {
var localVariable = n;
return localVariable;
}
var wrap1 = wrapValue(1);
var wrap2 = wrapValue(2);
console.log(wrap1);
console.log(wrap2);
And that works as expected.
Method 1 is simply just wrong.
When you call wrapValue you return localVariable which is set to 1 and 2, those are numbers and cannot be called as functions.
This is also what you experience in method 1.1.
As for method 2, that could be a way to isolate variables that you do not want to flow into the parent scope. It is not useful in your example, but it is widely in cases where you immediately call the defined function, e.g.:
var myFn = function() {
var hiddenVar = 1;
return function() {
return hiddenVar;
};
}();
I could answer your first question: Why does method 1 not work?
When you do var localVariable = n; you creates a new variable called localVariable and assigned it the type number and value n. And you return this integer value n.
Hence, wrap1 and wrap2 are numbers. They do not support () operation which only apply to functions. In method 1.1, you log wrapValue(...) directly which is the same as logging a number, which works.
Hope you could understand. :)
In your first exemple, you assign to wrap1 & 2 the return of the function which are numbers, and then you call the given numbers as functions.
var wrap1 = wrapValue(1); // wrap1 = 1;
var wrap2 = wrapValue(2); // wrap2 = 2;

assign a copy of a function to a var

Is it possible to define a function and then assign copies of the function to different vars?
This is essentially how far I've got...
function add(x, y){
return x + y;
}
var function1 = new add()
var function2 = new add()
This doesn't seem to work as it's trying to run the add function each time. The same goes for
var function1 = new function add()
Do I need to be using prototype in some way or am I looking at it in the wrong way?
This should do the trick
var function1 = add;
var function2 = add;
You are evaluating the function. To assign the function itself to a variable, use
var function1 = add;
var function2 = add;
However, it's not quite clear why you want to copy the function.
if your just trying to create references to the function just make this modification
function add(x, y){
return x + y;
}
var function1 = add;
var function2 = add;
After which you are able to call the functions like this.
function1(10,11);
function2(1,2);
A function in Javascript is an object as any other.
You can create many references to the same function and store them for example in an array
function add(x, y) {
return x + y;
}
var v = [add, add, add, add];
alert(v[3](33, 9)); // Will show 42
The only "magic" thing happens when you call a function getting it from an object member lookup
x = {};
x.f = add;
x.f(12, 3); // Returns 15
the "strange" thing that will happen is that this inside the function when called that way will be the object, and not the global window object as it happens when you call a function directly.
This also means that, confusingly enough,
x.f(z);
is not the same as
[x.f][0](z);
or as
var ff = x.f;
ff(z);
because in the first case this will be x, in the second case this will be the array instead and in the third case it will be the global window object.

how to declare a global variable assign value in one function and use in another function in javascript

I just write a test html file to learn about object in javascript. The code is as follows
in script tag
<script type="text/javascript">
var obj = new ParentFn();
var obj2 = new AnotherParentFn();
var temp;
function initer()
{
temp = obj.Adding();
obj2.caller();
}
function ParentFn()
{
this.a = 10;
this.b = 20;
}
function AnotherParentFn()
{
this.a = 30;
this.b = 50;
}
AnotherParentFn.prototype.caller = function()
{
var self = this;
temp();
}
ParentFn.prototype.Adding = function()
{
var self = this;
document.getElementById("id_div1").innerHTML = " Method Called and Result of a+b is " + (self.a + self.b);
}
</script>
In body i use
<button onclick="initer()"> Click here to test </button>
<div id="id_div1"></div>
Problem is when AnotherParentFn.prototype.caller is called from initer() function temp variable is still undefined. What is wrong with the code??
My task is to assign the function ParentFn.prototype.Adding in a global variable and call the global variable from AnotherParentFn.prototype.caller function. How to achieve it?
You don't need to save it as a global variable. It's already saved in ParentFn.prototype. All you need to do is invoke it with .call and pass in your desired receiver. You can implement AnotherParentFn.prototype.caller like this:
AnotherParentFn.prototype.caller = function()
{
ParentFn.prototype.Adding.call(this);
}
This way you can get rid of temp completely. You also don't need to assign this to a local var self everywhere.
Parentheses are used to execute a function.
When you assign the value to temp, you are calling the function and assigning the result (undefined) to temp. To store a reference to the function in temp, omit the parentheses.
temp = obj.Adding;
By writing temp = obj.Adding(); it stores the return value. not function pointer in temp. Use this
function initer()
{
temp = obj.Adding;
obj2.caller();
}
First of all, the reference to obj.Adding is not assigned properly; it should be this (without parentheses):
function initer()
{
temp = obj.Adding;
obj2.caller();
}
Then, inside AnotherParentFn.prototype.caller itself, you must pass the current object as this explicitly during the invocation by using .call():
AnotherParentFn.prototype.caller = function()
{
temp.call(this);
}

Categories

Resources