This question already has answers here:
Callback function - use of parentheses
(4 answers)
Closed 6 years ago.
Why don't I need to use () to call a function within a 'for' loop or within an '.addEventListener()' method? For example:
function activitiesReset()
{activitiesLegend.style = '';
}
for (var i=0; i<checkboxes.length; i++) {
checkboxes[i].addEventListener('change', activitiesReset);
}
In the addEventListener method, I first tried calling my function like activitiesReset(), but this did not work. Removing the () from the end of the function worked.
Why is that?
checkboxes[i].addEventListener('change', activitiesReset) is not calling activitiesReset. It is passing activitiesReset as an argument. activitiesReset is a function itself; activitiesReset() is a call to a function, evaluating to its return value. You want to set the event listener to your function, not to undefined (which is the result of calling your function).
The key to understanding this is the fact that functions in JavaScript are also values, just like numbers or strings or objects. (In fact, they are a specific kind of object.)
var adderFuncValue = function(x, y) { return x + y; };
function multiplierFuncValue(x, y) { return x * y; };
function callFuncWithTwoParams(func, p1, p2) {
func(p1, p2);
}
callFuncWithTwoParams(adderFuncValue, 3, 5); // 8
callFuncWithTwoParams(multiplierFuncValue, 2, 3); // 6
var someFunc = adderFuncValue;
someFunc(7, 8); // 15
So just like I'm passing functional values into callFuncWithTwoParams, you are passing a functional value into addEventListener. The browser will remember that function and associate it with change event, and call it -- later.
Related
This question already has answers here:
es6 how to use default parameters that go before non-default parameters?
(4 answers)
Closed 2 years ago.
It's practical to have the last parameter with a default value, as follows.
function add(x, y = 5) {
return x + y;
}
console.log(add(3)); // results in '8'
However, is it possible to have other than the last parameter with a default value? If so, how would you call it with the intention of using the first default value, but providing the second parameter?
function add(x = 5, y) {
return x + y;
}
console.log(add(,3)); // doesn't work
You still need to provide the first parameter regardless of its default value.
Try destructuring a single parameter instead, like this:
function add({ x = 5, y }) {
return x + y;
}
console.log(add({ y: 3 })); // results in '8'
You will still have to specify the y key, though, but this is a way better practice. 😄
You still could keep your add function the same by call it with params from destructed array like below snippet
function add(x = 5, y) {
return x + y;
}
console.log(add(...[,3]));
This question already has answers here:
What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript?
(14 answers)
Closed 3 years ago.
I was given the following solution to an exercise:
var s = [23, 65, 98, 5];
Array.prototype.myMap = function(callback) {
var newArray = [];
// Add your code below this line
this.forEach(a => newArray.push(callback(a)));
// Add your code above this line
return newArray;
};
var new_s = s.myMap(function(item) {
return item * 2;
});
the idea is to build your own replacement for .map() method.
My problem is to understand the callback part. So far my understand of a callback, is a funct that is passed into another function (as an arg) and is called after something else.
I cannot see where is another function being passed in as the callback in the solution, so I'm struggling to understand the exercise, mainly: this.forEach(a => newArray.push(callback(a)));
Is there anyone who could clarify this for me?
You can easily visualize synchronous callbacks by replacing the call with the functions code itself.
In your function call, callback is equal to:
function(item) { return item * 2; }
If we insert that into this line:
this.forEach(a => newArray.push(callback(a)));
we get:
this.forEach(a => newArray.push(
/*item = a*/
/*return*/ a * 2;
));
Or in other words, for each a in the array, a * 2 gets pushed to the newArray.
I'm trying to expand my modest level of JavaScript skills by learning how to use closures. In the code below, I thought I'd see console.log output counting down from 3 to 0. Instead, I'm getting -1, -1, -1, -1.
I know I'm dealing with scoping issues, but that's about it. What's missing? How should this be properly written, and why?
function closure_count_test (number)
{
for (var x = 0; x <= number; x += 1)
{
setTimeout(function() {console.log(number - x);}, x * 1000);
}
}
closure_count_test(3);
Your logic is correct. The problem is that setTimout only considers the latest value of the variables. So the setTimout always get x = 0 since it is the last in the loop.
you can see your desired output if you remove the setTimout function.
x is iterated by the for loop, but the function in setTimeout uses the variable x, which is not interpolated at the time the function is created. This causes it to use whatever the final value of x is (because the setTimeouts execute after the loop completes).
In order to get around this, you have to pass the value of x as it is to the callback of setTimeout. You can call a function that returns another function (the new callback):
for (var x = 0; x <= number; x += 1) {
setTimeout(
(function (x) {
return function () { console.log(number - x) };
})(x)
, x * 1000);
}
This passes x from the outer scope with its current value to the inner scope. The inner function uses whatever value x was when the function was created.
A function is returned to work properly with setTimeout.
http://jsfiddle.net/ExplosionPIlls/QhA3a/
How scoping works in basic words is, it makes variables of a main function, that are referenced in nested functions stay after function ends, and all of these functions can later access them.
In provided example x is a variable defined in the main function, and all nested functions will later be able to reference it. By that time the value of x will be number+1, so your result makes perfect sense. To workaround that, you must avoid referencing the variable of the main function. Here's the normal technique:
function closure_count_test (number)
{
for (var x = 0; x <= number; x += 1)
{
setTimeout(function(x) {
return function() {console.log(number - x);}
} (x), x * 1000);
}
}
What you do here, is you call several nested functions, which have their own x copied as an argument, and each of these have one nested function that will reference that argument via scope.
this works because x being to be localised inside one more closure
function closure_count_test(number) {
for (var x = 0; x <= number; x++) ( // not need {} as here is only one operator
function (x) { //Now x - local variable in anonymous function
return setTimeout(function () {
console.log(number - x);
}, x * 1000);
}(x) // pass x to anonymous function as argument
);
}
closure_count_test(3);
In JavaScript, how could you create a new function with the same name as an existing function, while also preserving the original function so it could be called from within the new one?
You can pass the original function into an anonymous function which returns a replacement function which has access to the original function.
E.g.
parseInt = (function parseInt(original) {
return function (x) {
console.log("original would've returned " + original(x));
// just random 'new' functionality
return (x | 0) * 2;
};
}(parseInt));
Example output:
>> parseInt(10);
<< original would've returned 10
<< 20
You want to implement function wrapping, check the following articles:
Wrapping Functions in JavaScript
Function Wrapping
You could simply assign the old function to a variable with a different name:
var old_parseInt = parseInt;
function parseInt(s) {
return old_parseInt(s) + 1;
}
This question already has answers here:
how do I compare 2 functions in javascript
(6 answers)
Closed 6 years ago.
how to compare two static functions in javascript equal or not equal?
String(f1) === String(f2)
var f1 = f2 = function( a ){ return a; };
here, you can use f1 === f2 because they're pointing to the same memory and they're the same type
var f1 = function( a ){ return a; },
f2 = function( a ){ return a; };
here you can use that byte-saver Andy E used (which is implicitly converting the function to it's body's text as a String),
''+f1 == ''+f2.
this is the gist of what is happening behind the scences:
f1.toString( ) == f2.toString( )
Edit: Looking back on this post over a year after, I agree with #kangax - you should probably never do this.
Whenever I need to compare functions I make sure there is no scope ambiguity and use the same function object.
Say I have some a pair of library functions that take a callback as one of the parameters. For the sake of this example create1minuteCallback function will set a 1 minute timer and call the callback on each tick. kill1minuteCallback will turn off the callback and you must pass the same callback function as you did for create1minuteCallback.
function create1minuteCallback(callback){
//implementation
}
function kill1minuteCallback(callback){
//implementation
}
Quite clearly this will not work as the function we are passing is different on the second line:
create1minuteCallback(function(){alert("1 minute callback is called");});
kill1minuteCallback(function(){alert("1 minute callback is called");});
I normally do this:
function callbackFunc(){alert("1 minute callback is called");}
create1minuteCallback(callbackFunc);
kill1minuteCallback(callbackFunc);
Well, as simply as that - if you are going to compare functions, you do it for a reason I assume. What is your reason?
My reason was to not run a certain function twice.
I did it this way (just snippet code to get the idea)
var x = function(){
console.error("i am a functionX");
}
var y = function(){
console.error("i am a functionX");
}
var z = function(){
console.error("i am a functionZ");
}
var x2= x;
var obj = new Object();
obj[x] = "";
obj[x2] = "";
obj[y] = "";
obj[z] = "";
obj.abc = "xaxa";
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.error(obj[prop] + " hello " + prop);
}
}
Function x and y are the same, even though they have different whitespaces. x and y are not the same as z, since z has a different console.error.
Btw open your firebug console to see it in the jsbin example