JS Bin example
Why does it not count, my output is always 1 in the console. I am new to closures and I must be missing something simple? Here is the code from the jsbin:
var counterFunc = function()
{
var count = 0;
var incCount = function()
{
count = count + 1;
return count;
};
return incCount();
};
var myCounter = counterFunc;
console.log(myCounter());
console.log(myCounter());
By returning incCount() - the result of the invocation - from your counterFunc, you're not really creating a closure function. You want to return a function, and invoke the counterFunc() to create it:
var counterFunc = function() {
var count = 0;
var incCount = function() {
count = count + 1;
return count;
};
return incCount ;
// ^
};
var myCounter = counterFunc();
// ^^
console.log(myCounter());
console.log(myCounter());
You should be returning the inner function itself, not the result of calling it
You therefore need to replace return incCount() with:
return incCount;
You subsequently need to directly invoke counterFunc() when you declare myCounter:
var myCounter = counterFunc(); // myCounter is now the closure
Only then will myCounter be assigned a reference to the inner function, that happens to hold a "closure" over the local variable count.
Related
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
I want to create some elements of a particular number, inside a loop, store them in a variable, then access that variable outside that loop.
The reason I want to access that variable outside the loop is so that I can put them inside an append function.
function range(start, stop, step) {
var a = [start],
b = start;
while (b < stop) {
b += step;
a.push(b);
}
return a;
}
var yAxis = range(1, 100, 10);
$.createAxis = function(axisValues) {
$(axisValues).each(function(index, element) {
yAxisNav = document.createElement('div');
var newValue = document.createTextNode("I have content!");
yAxisNav.appendChild(newValue);
return yAxisNav.className = 'graphBar_yAxis_label';
});
}(yAxis);
console.log(yAxisNav);
//$('body').append('<section>'+yAxisNav+'</section>');
The above only returns one element, how can I store this so that its accessible outside that loop?
As you wants to return a list of div's, I have moved yAxisNav outside function and appending it with every loop.
I think you are looking for this...
var yAxisNav = "";
$.createAxis = function (axisValues) {
$(axisValues).each(function (index, element) {
var elem;
elem = document.createElement('div');
var newValue = document.createTextNode("I have content!");
elem.appendChild(newValue);
elem.className = 'graphBar_yAxis_label';
yAxisNav += elem.outerHTML;
});
return yAxisNav;
}(yAxis);
console.log(yAxisNav);
$('body').append('<section>'+yAxisNav+'</section>');
Get the value returned by createAxis
return yAxisNav object from the function. This should be the last statement in the function createAxis,
return yAxisNav;
And then you can get it as follow:
var yAxisNav = $.createAxis(something);
CODE
$.createAxis = function(axisValues) {
$(axisValues).each(function(index, element) {
yAxisNav = document.createElement('div');
var newValue = document.createTextNode("I have content!");
yAxisNav.appendChild(newValue);
yAxisNav.className = 'graphBar_yAxis_label'; // Move up
return yAxisNav; // Return complete object
// ^^^^^^^^^^^^^
});
}(yAxis);
As mentioned here, define the variable in the highest scope in which you want to access it.
In this case, define it outside the range function.
In the for loop below, when I console.log searchTermsList[i] the first time (console.log('searchTermsList[i] is:' + searchTermsList[i]);), it works correctly and prints out the respective string.
However, when I do it again later in the code (console.log('the searchTermsList[i] Im about to use for the query is:' + searchTermsList[i]);), it prints out that it's undefined. Both console.logs are within the same loop, so why isn't the 2nd one able to find the value?
for (var i = 0; (i < top3List.length) && (i < searchTermsList.length); i++){
console.log('searchTermsList[i] is:' + searchTermsList[i]);
console.log('top3List[i] is:' + top3List[i]);
var MCI_Results = Parse.Object.extend("MCI_Results");
var MCI_Results_Comparison_Query = new Parse.Query(MCI_Results);
// Compare respective items' MCI_Results array to eBay results (top3List[i])
MCI_Results_Comparison_Query.equalTo('parent', user);
MCI_Results_Comparison_Query.contains('searchTerm', searchTermsList[i]);
MCI_Results_Comparison_Query.containsAll('Results', top3List[i]);
MCI_Results_Comparison_Query.find()
.then(function(results) {
// No new items, Results and top3List[i] are identical
if (results.length > 0) {
console.log('done updating channel');
}
// New items found, Results and top3List[i] don't match.
else {
console.log('no matching MCI_Results, lets push some new shit');
// Find MCI_Results object for specific item
var MCI_Results_Update_Query = new Parse.Query(MCI_Results);
MCI_Results_Update_Query.equalTo('parent', user);
console.log('the searchTermsList[i] Im about to use for the query is:' + searchTermsList[i]);
MCI_Results_Update_Query.contains('searchTerm', searchTermsList[i]);
// Update MCI_Results with new top3List eBay results
MCI_Results_Update_Query.find()
.then(function(results) {
console.log('totally just updated the MCI_Results, NBD');
})
.then(function() {
// Check for high priority MC items
});
}
});
}
i is a mutable variable. i++ will change i to point to a different index by the time that function is called.
You'll need to create a new variable in a new scope, possibly using an immediately-invoked anonymous function, and not change it.
An example:
var makeBadAdders = function(n) {
var adders = []
for (var i = 0; i < n; i++)
adders[i] = function(x) {
// Closes over a mutable variable.
// Function will use the most up-to-date value of i.
return i + x;
}
return adders
}
var badAdders = makeBadAdders(3);
console.log(badAdders[1](1)); // 4
console.log(badAdders[2](1)); // Also 4
var makeAdders = function(n) {
var adders = []
for (var i = 0; i < n; i++)
adders[i] = makeAdder(i);
return adders
}
var makeAdder = function(i) {
// Closes over an effectively immutable variable (i).
return function(x) {
return x + i;
}
}
var goodAdders = makeAdders(3);
console.log(goodAdders[1](1)); // 2
Note that you could write makeAdder inline like so:
adders[i] = (function(i) {
return x + i
})(i)
(This shadows the outer, mutable i.)
But usually, it's better to just avoid mutable variables and use something like forEach instead. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
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.
I have a function that replaces characters from a string
function ratko(a) {
var k = a.toString();
var z = k.replace(/\,/g, '], [');
var s = z.replace(/\./g, ', ');
var final = "[[" + s + "]]";
alert(final);
}
What I need is to get the value of final outside the function like this:
var outsideValue = final;
EDIT!!! --
function ratko() gets it's value from ajax
success: function (data) {
if (data.success) {
alert("Note: This month has " + data.holidays.length + " holidays.");
praznici = data.holidays;
ratko(praznici);
}
else {
alert(data.ErrorMessage);
}
Possibility 1:
function ratko (a) {
...
return final;
}
var outsideValue = ratko (...);
Possibility 2:
var final;
function ratko (a) {
// no var final declaration here
...
}
...
ratko (...);
// now final has the value assigned to it in the function
You can access variables declared in an outer scope in an inner scope, which is what you do in Possibility 2.
One option would be to use a global variable, just declare it outside of the function.
var myvar = 1;
function myFunction()
alert(myvar); // 1
}
You can read more on javascript variables here.
You declare it outside the function scope:
var finalVar;
function ratko(a) {
var k = a.toString();
var z = k.replace(/\,/g, '], [');
var s = z.replace(/./g, ', ');
finalVar= "[[" + s + "]]";
alert(finalVar);
}
var outsideValue = finalVar;
Beware final is a reserved keyword in Javascript. I changed its name.
Besides that, keep in mind that Javascript is always parsed from top to bottom. So using a variable before declaring it will definitely give you an undefined.
you must be modify your function code like this
function ratko(a) {
var k = a.toString();
var z = k.replace(/\,/g, '], [');
var s = z.replace(/./g, ', ');
var final = "[[" + s + "]]";
//alert(final); comment this code line and replace this with the code above
return final;
}
after you can call your function ratko with this simple code
var inputValue = 'simple message';
var parsedValue = ratko(inputValue);
you find the final value into a new variable parsedValue