Can I pass additional parameters to JavaScript map() callback function? [duplicate] - javascript

This question already has answers here:
Pass an extra argument to a callback function
(5 answers)
Closed 6 years ago.
I have an array and now I want to execute a function on every element in the array.
I'm trying to use map() function. The question is, my callback function passed to map() has its own parameters (not element, index, array).
Can I pass parameters to such a callback function? How?

I can think of 2 different ways:
Using thisArg to set an options object as the this value in the callback:
var numbers = [1,2,3,4,5,6,7,8,9,10];
function callback(element) {
return element + this.add;
};
var mapped = numbers.map(callback, {
add: 10
});
console.log(mapped);
Using .bind() to set some arguments:
var numbers = [1,2,3,4,5,6,7,8,9,10];
function callback(add, element) {
return element + add;
};
var mapped = numbers.map(callback.bind(null, 10));
console.log(mapped);

I think you might need to wrap your original function in another callback function, like this:
var array = ['one', 'two', 'skip-a-few', 'three', 'four']
console.log(
array.map(function (element) {
return original('other', 'variables', element)
})
)
// this function doesn't matter, just an example
function original(a, b, c) {
return a + ' ' + b + ' ' + c
}

Related

Explain API function signature syntax [duplicate]

This question already has answers here:
How to interpret function parameters in software and language documentation?
(4 answers)
Closed 2 years ago.
Reading documentation for a few years I've often been confused by the syntax commonly used in explaining function signatures. for instance:
From the Mozilla Array.map Docs:
var new_array = arr.map(callback[, thisArg])
The docs list three arguments for the callback: currentValue, index, and array, but the signature just has this weird callback[, thisArg] syntax. Whats the deal with that comma? why are there array brackets next to 'callback'? Is there any documentation out there on this syntax? is there a name for this syntax? any help would be appreciated.
Thanks!
The function Array.prototype.map expects a function as the first argument:
var new_array = arr.map(callback[, thisArg])
The square brackets indicate that the secondparameter is optional. You can call Array.prototype.map with or without a second argument. Both functions calls are valid:
var array = [1, 2, 3, 4];
var myFunc = function (number) {
return number * 5;
};
var myFuncUsingThis = function (number) {
console.log(this);
return number;
};
var myThisArg = {
foo: 'bar'
};
console.log(array.map(myFunc));
console.log(array.map(myFuncUsingThis, myThisArg));
The last is the same as
console.log(array.map(myFuncUsingThis.bind(myThisArg)));
So, if the function that you provide to Array.prototype.map uses the this object, you can specify the this object of the function when it is called by Array.prototype.map by using the second (optional) argument.
currentValue, index and array are something completely different. You do not have to provide them when you call Array.prototype.map. Instead, Array.prototype.map provides them for you: it calls the function that you gave it with those three arguments (but you don't have to use all three arguments).
The first argument to your function is the value of the element in the array that is currently processed, the second argument is the index of that element, and the third argument is the array itself.
You can write a function that takes use of the index parameter:
var array = Array(20).fill(0); // an array containing 20 zeros
var evenNumbers = array.map(function (number, index) {
// number is zero, index is the index of the element we should transform
return index * 2;
});
console.log(evenNumbers);
Maybe it helps if you take a look at a (naïve) implementation of Array.prototype.map:
Array.prototype.map = function (callback, thisArg) {
// "this" is the array on which we work
var arr = []; // the new array that we build
var result;
for (var i = 0; i < this.length; i += 1; i++) {
result = callback.call(thisArg, this[i], i, this);
arr[i] = result;
}
return arr;
};
The parameters inside the brackets mean they are optional.

How to use apply with currying?

I have code that is using currying to get the average on an array that results from concatenating two arrays: an n size array and an m size array.
var avg = function(...n){
let tot=0;
for(let i=0; i<n.length; i++){
tot += n[i];
}
return tot/n.length;
};
var spiceUp = function(fn, ...n){
return function(...m){
return fn.apply(this, n.concat(m));
}
};
var doAvg = spiceUp(avg, 1,2,3);
console.log(doAvg(4,5,6));
In this line return fn.apply(this, n.concat(m));, I don't understand why do we need to use apply. What is the object we are binding with the average function and why does just normal calling (return fn(n.concat(m));) not work?
In that example, this is not that important. It would also work if instead of this you would pass an empty object instead. It's just an example on how to use apply.
What you need to focus is on the second parameter n.concat(m). They key concept here is that passing an array as a second argument you are calling that function (fn) passing each value in the array as an argument.
About your second question: no, it won't work because fn expects several arguments (one per value to calculate the average) while by doing return fn(n.concat(m)); you are just passing one argument, an array containing all values
Maybe you would understand it better with a simpler example:
function sum3params(a,b,c){
return a+b+c;
}
console.log(sum3params([3,4,2])) // won't work
console.log(sum3params.apply(this, [3,4,2])) // will work ('this' is not important here)
For this use case, it does not. But consider the following:
var foo = {
bar: 3
};
var addBar = function(a, b) { return a + b + this.bar };
foo.add3AndBar = spiceUp(addBar, 3);
foo.add3AndBar(1); // 7
Using apply means that your spiceUp function can be applied to methods as well as normal functions. For more likely example, consider partially applying when defining a method on a prototype:
const ENV = "linux";
DoesSomePlatformSpecificStuff.prototype.getPath = spiceUp(ENV);
apply also will spread the gathered array of arguments back out into positional arguments which can also be done like so:
return fn(...n.concat(m));
Which can be simplified as
return fn(...n, ...m);
Which is equivalent to
return fn.apply(undefined, n.concat(m));

common function that accept all argument in javaScript [duplicate]

This question already has answers here:
JavaScript variable number of arguments to function
(12 answers)
Closed 6 years ago.
often time I have this pattern problem in javascript. I have an add function
function add(a, b){
return a + b;
}
then I can do add(1,2) //3
but what if I want to pass in any length of arguments?
I can't do freely add(1,2,3,4). or add(something,something,something). If I want I have to write another add function that accept 4 and 3 arguments.
I know I can use loop them up by loop but how to pass any number of argument to a function in js?
you can use arguments property .
function add(){
var sum=0;
for (var key in arguments)
sum=sum+arguments[key];
return sum;
}
console.log(add(1,2,3,7));
You can loop over arguments and add values
ES6
function add(){
return Array.from(arguments).reduce((p,c)=>p+= !isNaN(c)? +c : 0, 0)
}
console.log(add(1,2,3,4,5))
console.log(add(1,2,3,'a', 7))
ES5
function add(){
return [].slice.call(arguments).reduce(function(p,c){
p+= !isNaN(c)? +c : 0;
return p;
}, 0)
}
console.log(add(1,2,3,4,5))
console.log(add(1,2,3,'a', 7))

JavaScript: How to pass extra parameters to a callback [duplicate]

This question already has answers here:
Pass an extra argument to a callback function
(5 answers)
Closed 6 years ago.
I have a question which has bugged me for a while now.
Let's say I have the following array:
var array = [1, 2, 3]
Now I have a function similar to this:
function print(num, str) {
console.log(str + ": " + num);
}
Is it possible to call the forEach method and pass a string to it?
// how do I pass "str"?
array.forEach(print);
Thanks!
You have two options here:
Either you swap the arguments, so that str comes first. Then you can use function.bind to bind the first arguments of the function:
function print(str, num) {
console.log(str + ": " + num);
}
array.forEach(print.bind(null, 'someStr'));
Alternatively, you can also create a new (anonymous) function which simply passes some value to the second argument:
array.forEach(function (item) { print(item, 'someStr'); });
With ES6 and the arrow functions, this even gets a bit prettier:
array.forEach(item => print(item, 'someStr'));
Both solutions have a very similar effect in that they create a new function object which is then passed to forEach. What makes more sense to you depends on your use cases.
And just as a note: You just need to remember that the callback passed to forEach actually takes up to three arguments (the item, the item’s index, and the array itself), so be careful when you pass a function that accepts other additional arguments. You can again use a local function to remedy that.
Not in this particular situation. The simple solution here is to use an anonymous function wrapper:
array.forEach(function (i) { print(i, str); });
If you reversed the parameters to print, you could do this a little more elegantly like so:
function print(str, num) { .. };
array.forEach(print.bind(null, str));
str will be bound as the first parameter, any parameters that forEach passes when invoking the callback are passed in second, third etc. place.
Here you go
var array = [1, 2, 3];
function print(str, num) {
console.log(str + ": " + num);
}
var str = 'someString';
array.forEach(print.bind(null, str));

Why is my return value undefined (JavaScript) [duplicate]

This question already has answers here:
Jquery each - Stop loop and return object
(6 answers)
Closed 9 years ago.
I have an array called questionSets full of objects. The createSet function should create new or create a copy of an existing questionSets object. The function getQuestionsFromSet is used if createSet is used to make a copy. For some reason when I call getQuestionsFromSet() from inside createSet() I always get a returned value of 'undefined'. I can't figure out why because when I do a console.log() of the value to be returned by getQuestionsFromSet() I see exactly what I want.
I have these two functions.
function createSet(name, copiedName) {
var questions = [];
if (copiedName) {
questions = getQuestionsFromSet(copiedName);
}
console.log(questions); // undefined. WHY??
questionSets.push({
label: name,
value: questions
});
}; // end createSet()
function getQuestionsFromSet(setName) {
$.each(questionSets, function (index, obj) {
if (obj.label == setName) {
console.log(obj.value); // array with some objects as values, which is what I expect.
return obj.value;
}
});
}; // end getQuestionsFromSet()
Because getQuestionsFromSet() does not return anything and so is implicitly undefined.
What you need is probably something like:
function getQuestionsFromSet(setName) {
var matched = []; // the array to store matched questions..
$.each(questionSets, function (index, obj) {
if (obj.label == setName) {
console.log(obj.value); // array with some objects as values, which is what I expect.
matched.push(obj.value); // push the matched ones
}
});
return matched; // **return** it
}
return obj.value; is nested within the inner $.each(function{}), and getQuestionsFromSet is indeed not returning anything.

Categories

Resources