My point is this:
function sum(...arguments) {
if (arguments.length === 1) {
const [firstArg] = arguments;
if (firstArg instanceof Array) {
return sum(...firstArg)
}
}
return arguments.reduce((a, b) => a + b);
}
What is this ... are doing infront of arguments. And also please help me know that why const [firstArg] is given and how this is working. And please explain me instanceof in easy words. My native language is not english. Thank you so much.
That's the rest syntax:
The rest parameter syntax allows a function to accept an indefinite number of arguments as an array.
This:
const [firstArg] = arguments;
is destructuring assignment:
[it] makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
Re instanceOf:
The instanceof operator tests to see if the prototype property of a constructor appears anywhere in the prototype chain of an object. The return value is a boolean value.
Unpacking this code:
function sum(...arguments) {
// arguments is an array thanks
// to the rest syntax. If it has a length of
// one...
if (arguments.length === 1) {
// Get the first element
const [firstArg] = arguments;
// If that element is an array
if (firstArg instanceof Array) {
// Call sum again with that element
return sum(...firstArg)
}
}
// Return the sum of the arguments
return arguments.reduce((a, b) => a + b);
}
Your function could be easily simplified by flattening the arguments, and then using reduce to return the sum. And this way you can even have a set of single values passed in, or n multiple arrays as a single argument to the function, or a mixture of both.
function sum(...args) {
return args.flat().reduce((acc, c) => acc + c, 0);
}
console.log(sum(1, 2, 3));
console.log(sum([1], 1, 2, 3));
console.log(sum([1, 2, 3]));
console.log(sum([1, 2], [1, 4, 3]));
console.log(sum([1, 2], [12, 20], [1, 4, 3]));
(...arguments) is the rest parameter syntax and allows a function to accept an indefinite number of arguments as an array, providing a way to represent variadic functions in JavaScript.
for more information, you can read here
const [firstArg] = arguments;
is something named Destructuring assignment
The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
you can read more, here
and in the last, The instanceof operator tests to see if the prototype property of a constructor appears anywhere in the prototype chain of an object. The return value is a boolean value
This because ... is a javascript tool that allows you to put multiple parameters in a function it is called the rest parameter function.
Related
It was really confusing for me to read this syntax in Javascript:
router.route('/:id')
.put((...args) => controller.update(...args))
.get((...args) => controller.findById(...args));
What does ...args mean?
With respect to (...args) =>, ...args is a rest parameter. It always has to be the last entry in the parameter list and it will be assigned an array that contains all arguments that haven't been assigned to previous parameters.
It's basically the replacement for the arguments object. Instead of writing
function max() {
var values = Array.prototype.slice.call(arguments, 0);
// ...
}
max(1,2,3);
you can write
function max(...value) {
// ...
}
max(1,2,3);
Also, since arrow functions don't have an arguments object, this is the only way to create variadic (arrow) functions.
As controller.update(...args), see What is the meaning of "foo(...arg)" (three dots in a function call)? .
Essentially, what's being done is this:
.put((a, b, c) => controller.update(a, b, c))
Of course, what if we want 4 parameters, or 5, or 6? We don't want to write a new version of the function for all possible quantities of parameters.
The spread operator (...) allows us to accept a variable number of arguments and store them in an array. We then use the spread operator again to pass them to the update function:
.put((...args) => controller.update(...args))
This is transparent to the update function, who receives them as normal arguments.
The meaning of “…args” (three dots) is Javascript spread operator.
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// expected output: 6
If you know some Python syntaxes, it is exactly the same as *args. Since *args (Python) is tuple object and Javascript has no tuple like Python, ..args is an Array object.
means pass all values (useful if have unknown# of items)
sample code
console.log(sum(1, 2, 3, 4)); // expected output: 10
function sum(...allItems) {
let total = 0;
for (const item of allItems) {
total += item;
}
return total;
}
It's called 'rest parameter', you can use rest parameter to pass unspecified number of arguments as an array, And a function can have only one rest parameter and it have to be the last parameter for the function
function sum(...args){
let output = 0;
for(const num of args){
output += num;
}
return output;
}
console.log(sum(2,4,8));
here it takes the argument that passed on sum as an array and sum the output and return it
I have an object an a function which accept arguments, I would like to spread the objects so each property is an argument in that function.
What am I doing wrong in my code?
const args = {
a: 1
b: 2
}
const fn = (a, b) => a + b
// i am trying with no success
console.log(fn(...args))
Although the other answers are correct, they change the function signature to accept an object instead of 2 separate arguments. Here is how to use an object's values as function arguments without altering the function's signature. This requires Object.values (ES 2017) and the spread operator to be available in your runtime.
const args = {
a: 1,
b: 2
}
const fn = (a, b) => a + b
fn(...Object.values(args));
Keep in mind this will work only in your specific case, since Object.values returns the values of all object keys and doesn't guarantee alphabetical sort order. If you want to take only the values of properties which are named a and b, you can map over Object.keys(args) and filter only those values.
You can use ES6 object destructuring on passed parameter and then just pass your object.
const args = {a: 1, b: 2}
const fn = ({a, b}) => a + b
console.log(fn(args))
You can also set default values for those properties.
const args = {b: 2}
const fn = ({a = 0, b = 0}) => a + b
console.log(fn(args))
You need to do it like this
const fn = ({a, b}) => a + b
The other answers are certainly applicable in particular situations, still have some limitations as well. Therefore I'd like to propose a different approach. The idea is to add to the object a method that returns an array of desired parameters in the appropriate order. That method is executed when passed to target function as argument and result destructured with spread operator.
const args = {
a: 1,
b: 2,
argumentify: function () {
return [this.a, this.b];
}
};
const fn = (a, b) => a + b;
console.log(fn(...args.argumentify()));
Benefits of this approach:
1) Does not require changes of the target function's signature, so can be used to ANY function.
2) Guarantees correct order of parameters (which is (as I understand) not guaranteed when spreading object).
3) Can itself be parametrized if needed.
Turn the args to an array should work:
const args = [1, 2]
const fn = (a, b) => a + b
console.log(fn(...args))
See Replace apply() for details.
Why does the foo function work fine.
function foo (a,b) {
return arguments.length;
}
But, the boo function returns undefined is not a function, even though I pass arguments in the function.
function boo (a,b) {
return arguments.slice(0);
}
arguments is not an array, but an array-like object. Many array methods work on array-like objects, because they expect an object with numeric properties, and a length property, such as arguments. You can use the built-in functions by using call and passing the object as the this value:
var args = Array.prototype.slice.call(arguments);
//^ args is a real array now
This works with other methods as well, like reduce:
function sum(/*...args*/) {
return [].reduce.call(arguments, function(x, y){return x + y})
}
arguments is an object and not an array. If you print it and see, you can see an object:
function foo (a,b) {
console.log(arguments);
}
foo(10,20);
o/p: { '0': 10, '1': 20 }
From the docs,
This object contains an entry for each argument passed to the
function, the first entry's index starting at 0. For example, if a
function is passed three arguments, you can refer to the argument as
follows:
arguments[0] arguments[1] arguments[2]
It does not have any Array properties except length.
So, return arguments.slice(0); would fail, since slice belongs to the prototype of an array.
I have an array of arrays:
var data = [[2,2], [6,4], [300,500]];
I have a function that takes some arguments and returns a single value.
var sum = function (a, b) { return a + b; }
I want to apply the function to each item in the array, e.g.
FOO(data, sum) === [sum(2,2), sum(6,4), sum(300,500)] === [4, 10, 800]
I was hoping underscore would have a function that does what "FOO" does. But I don't see anything. _.map is close, but not quite.
I know how to implement the function FOO.
var FOO = function (arrayOfArrays, iterator, context) {
return _.map(arrayOfArrays, function (array) {
return iterator.apply(context, array);
}
)};
My question is what to call FOO. I'm guessing the above pattern is common enough in functional programming that there's already a well established, language-agnostic name for this function.
It seems to me there is already a standard Javascript method for arrays, forEach(), that does what you want. For example:
data.forEach(sum);
So, do you really need a new FOO? If so, you could name it "forEach" and just wrap the above logic.
Here is the test code:
function fn(i, j) {
arguments = [3, 4];
console.log(i, j); // 1, 2
console.log(arguments); // [3, 4]
}
fn(1, 2);
in the function , I reset the arguments object
However, the arguments object is changed, but the formal parameter which passed in is not chaned, I think they are the same, so what's the differences?
arguments is an array-like object, which has reference to all the parameters passed to it. Here, you have merely reassigned arguments to point to some other object. If you want to change the actual parameters, you have to change the elements of arguments, like this
function fn(i, j) {
arguments[0] = -1;
console.log(i, j); // -1, 2
console.log(arguments); // { '0': -1, '1': 2 }
}
fn(1, 2)
Quoting from arguments, MDN docs
The arguments object is not an Array. It is similar to an Array, but
does not have any Array properties except length. For example, it does
not have the pop method.
However it can be converted to a real Array:
var args = Array.prototype.slice.call(arguments);
If Array generics
are available, one can use the following instead:
var args = Array.slice(arguments);
You are replacing the arguments array (actually an array-like object) with a new array. They are separate objects and exist side by side. Replacing the reference of the arguments variable doesn't make the function use the new array as arguments, it still has an internal reference to the original object.
If you change the contents of the arguments object, it will reflect on the function arguments:
function fn(i, j) {
arguments[0] = 3;
arguments[1] = 4;
console.log(i, j); // 3, 4
console.log(arguments); // [3, 4]
}
fn(1, 2);