closure in JavaScript - javascript

I want the variable i to be a counter, but it is being initialized to 100 each time.
How do I call myFunction().f() directly?
function myFunction() {
var i=100;
function f() {
i=i+1;
return i;
}
return f(); // with parenthesis
};
var X = myFunction();
console.log(X);
X = myFunction();
console.log(X);

You can't call f directly. It is wrapped in a closure, the point of which is to close over all the local variable. You have to expose it to the outside of myFunction.
First:
return f; //(); // withOUT parenthesis
Then just call X, as you'll have assigned a function to it.
var X = myFunction();
X();

This example would return 101 and 102: Be sure to try it.
function myFunction() {
var i=100;
function f() {
i=i+1;
return i;
}
return f; // without any parenthesis
};
var X = myFunction();
// X is a function here
console.log(X());
// when you call it, variable i gets incremented
console.log(X());
// now you can only access i by means of calling X()
// variable i is protected by the closure
If you need to call myFunction().f() that will be a pointless kind of closure:
function myFunction() {
var i=100;
function f() {
i=i+1;
return i;
}
return {x : f}
};
var X = myFunction().x();
// X now contains 101
var X = myFunction().x();
// X still contains 101
// pointless, isn't it?

Related

Javascript and Hoisting

In my code, the x value is undefined. If I remove if block, the x value is displayed as 77. I don't understand why if block is modifying the x value.
var x = 77;
function fn() {
if (false) {
var x = 55;
}
console.log(x);
}
fn();
var x = 77;
function fn() {
if (false) {
var x = 55;
}
console.log(x); // undefind
}
fn();
In the intermediate phase, x will be hoisted to its scope:
var x = 77;
function fn() {
//var x = undefind; intermediate phase
if (false) {
var x = 55;
}
console.log(x);
}
fn();
var x = 77;
function fn() {
if (false) {
x = 55;
}
console.log(x); // 77
}
fn();
The x variable is redeclared and hoisted inside the function, but never set because if (false) will never be reached thus undefined. The outer x is known inside the function if you remove the inner declaration.
This can be solved by using const or let (ES6) instead of var. const and let is not hoisted and lives only inside of the brackets they are declared:
const x = 77;
function fn() {
if (false) {
const x = 55;
}
console.log(x); // 77
}
fn()
Another solution is to just use two different variable names or remove the var inside the if statement depending on your needs...
Inside the scope of the function, the variable x is hoisted to the top as follows var x; If you print it, you get undefined. It is never assigned a variable as it is not going inside the if block
Simply remove the var inside the if-statement. That will fix the hoisting issue.
var x = 77;
function fn() {
if(false) {
x = 55;
}
console.log(x); // 77
}
fn();
You can also use let keyword.
let x = 77;
function fn() {
if (false) {
let x = 55;
}
console.log(x); // 77
}
fn()
one should use wither ES6 define syntax const OR let while assigning the variable, if needs to mutate the variable then use let, otherwise use const , stop using var .
In your scenario while using var there, it means you are trying to re initialize the x, it gets hoisted
var x = 77; means
var x; outside the block.
So one should not need to re initialize the x just pass the value or either use let or const .
function fn() {
if (false) {
//
x = 55;
}
console.log(x);
}
fn();

Javascript - see if object contains function, if so, return it

I have a function which takes in a String. The function checks if the object in the list has this function(functionName). If it contains that function, how can I return it? Obviously, return list[i].message would work, but thats not what im after. I want do use the parameter functionName in this case.
function message(){
return "hello";
}
function test(functionName);
listLength = list.length;
for(i = 0; i < listLength; i++){
if(list[i].hasOwnProperty(functionName}{
return (?)
}
}
var x = test("message");
alert(x);
Grateful for response
the comment from Pointy is right, but you have to consider that having a function detached by its owner will screw the scope, so you will no longer have access to the right this object
var test = {
number: 0,
testFunction: function() {
return this.number;
}
}
console.log(test.testFunction()); // output: 0
var x = test.testFunction;
console.log(x()); // output: undefined
maybe you should use
var y = test.testFunction.bind(test);
console.log(y()); // output: 0

Undefined is not a function - JavaScript

I have a simple question here. Here is the code below
var num = 0;
var increment = function() {
return function() { num++; };
};
increment();
increment();
However, when I tried to run it, it errors with undefined is not a function. How come? Isn't increment clearly a function?
Also, when I wrote typeof increment, it returns undefined.
When increment() is called twice, it should modify num, and become 2.
I'm guessing you want to do something like this:
> var makeIncrement = function () { var num = 0; return function () { return num++ } }
undefined
> increment = makeIncrement()
function () { return num++ }
> increment()
0
> increment()
1
The function has to be called (makeIncrement()) in order to return the inner function, which you can then assign to a variable. Once it has been assigned, you can call it and it will work as you expect.
var num = 0;
var increment = function() {
num++;
};
increment();
increment();
but what are you returning with return function()? You should just return num.
var num = 0;
var increment = function() {
num++
return num;
};
var something = 0;
something = increment();
something = increment();
alert(something);
As per your comment, if you want to return a function from your function, call the function returned by increment() :
var num = 0;
var increment = function() {
return function() { num++; };
};
increment()();
increment()();
Or, better suited :
var incrementer = increment();
incrementer(); //Call this each time you want to increment num
It's not a function ... exactly. Your function "increment" returns a function, not the incremented value. The correct way should be:
var increment = function() { return num++; };
Phil
Yes, the increment function does not increment the variable; it returns an inner function that would increment the variable when invoked.
As written, you would have to invoke the result of invoking the increment function:
increment()(); //results in num++
OR
var incrementFunction = increment(); //does not increment
incrementFunction(); //num++
If you want to assign to increment the inner function, then you need to execute the outer function:
var increment = (function() {
return function() { num++; };
}());
(This is called an immediately-invoked function expression, or IIFE for short.) A simpler approach, of course, is:
var increment = function() { num++; };
but perhaps you have other reasons for wanting to do it in a more complicated way.

If I have a variable, assigned to the value of a function call, can that variable be updated if the function call's parameters are changed?

If I have a function, like this:
function f(x,y){
return x + y;
}
And if I have variables of parameters I want passed to f:
var parameter1;
var parameter2;
If I assign this function call to a variable:
var functionCallValue = f(parameter1,parameter2);
How can I ensure that functionCallValue changes depending on different values I assign to the variable parameter1 and parameter2?
I suppose what you need is a closure.
var servant = function(x, y) { return x + y; };
var param1 = 40;
var param2 = 2;
var master = function() { return servant(param1, param2) };
var result = master(); // 42.
param1 = 2;
param2 = 40;
var anotherResult = master(); // still 42, because that's really the answer!
functionCallValue is assigned the result (returnvalue) of your function f. (The function is called, the value calculated and the result handed over to your variable.) Thus functionCallValue does not automatically update, if you change the parameters (which would make no sense at all), you need to call the function again with the altered parameters.
For something like an auto-update you need a closure like this:
var asdf = (function(){
var param1 = 1;
var param2 = 2;
var result = param1+param2;
function compute(){
result = param1 + param2;
}
return{
param1:function(x){
param1 = x;
compute();
},
param2:function(x){
param2 = x;
compute();
},
result:function(){
return result;
}
}
})();
console.log(asdf.result()); // logs 3
asdf.param1(3);
console.log(asdf.result());​ // logs 5
Demo

What do I have to do with the variable count in order to pass this tutorial about JavaScript function scopes?

The tutorial says:
Define a function named callFunc that takes one argument, a function
f. It should return an array containing the values f(0), f(0), f(1),
f(1). You can only call f twice.
This is what the tutorial gives:
var count = 0;
var f = function (x) {
count += 1;
return x + 2;
};
var callFunc = function (f) {
};
I have no idea how to use count to pass this tutorial.
Any suggestions?
You don't need to use count. Just call f() twice and put the return values into an array:
var callFunc = function (f) {
var f0 = f(0);
var f1 = f(1);
return [f0, f0, f1, f1];
};

Categories

Resources