Passing an array as a function parameter in JavaScript - javascript

I'd like to call a function using an array as parameters:
const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it
function call_me (param0, param1, param2 ) {
// ...
}
Is there a better way of passing the contents of x into call_me()?

const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);
See MDN docs for Function.prototype.apply().
If the environment supports ECMAScript 6, you can use a spread argument instead:
call_me(...args);

Why don't you pass the entire array and process it as needed inside the function?
var x = [ 'p0', 'p1', 'p2' ];
call_me(x);
function call_me(params) {
for (i=0; i<params.length; i++) {
alert(params[i])
}
}

In ES6 standard there is a new spread operator ... which does exactly that.
call_me(...x)
It is supported by all major browsers except for IE.
The spread operator can do many other useful things, and the linked documentation does a really good job at showing that.

Assuming that call_me is a global function, so you don't expect this to be set.
var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);

As #KaptajnKold had answered
var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);
And you don't need to define every parameters for call_me function either.
You can just use arguments
function call_me () {
// arguments is a array consisting of params.
// arguments[0] == 'p0',
// arguments[1] == 'p1',
// arguments[2] == 'p2'
}

While using spread operator we must note that it must be the last or only parameter passed. Else it will fail.
function callMe(...arr){ //valid arguments
alert(arr);
}
function callMe(name, ...arr){ //valid arguments
alert(arr);
}
function callMe(...arr, name){ //invalid arguments
alert(arr);
}
If you need to pass an array as the starting argument you can do:
function callMe(arr, name){
let newArr = [...arr];
alert(newArr);
}

Function arguments may also be Arrays:
function foo([a,b,c], d){
console.log(a,b,c,d);
}
foo([1,2,3], 4)
of-course one can also use spread:
function foo(a, b, c, d){
console.log(a, b, c, d);
}
foo(...[1, 2, 3], 4)

Note this
function FollowMouse() {
for(var i=0; i< arguments.length; i++) {
arguments[i].style.top = event.clientY+"px";
arguments[i].style.left = event.clientX+"px";
}
};
//---------------------------
html page
<body onmousemove="FollowMouse(d1,d2,d3)">
<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>
</body>
can call function with any Args
<body onmousemove="FollowMouse(d1,d2)">
or
<body onmousemove="FollowMouse(d1)">

you can use the spread syntax
for example:
function print(...inpu){
console.log(...inpu)
}
var arry = ['p0','p1','p2']
print(...arry)
here is the link: modzilla spread syntax refrence document

you can use spread operator in a more basic form
[].concat(...array)
in the case of functions that return arrays but are expected to pass as arguments
Example:
function expectArguments(...args){
return [].concat(...args);
}
JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))

The answer was already given, but I just want to give my piece of cake. What you want to achieve is called method borrowing in the context of JS, that when we take a method from an object and call it in the context of another object. It is quite common to take array methods and apply them to arguments. Let me give you an example.
So we have "super" hashing function which takes two numbers as an argument and returns "super safe" hashed string:
function hash() {
return arguments[0]+','+arguments[1];
}
hash(1,2); // "1,2" whoaa
So far so good, but we have little problem with the above approach, it is constrained, only works with two numbers, that is not dynamic, let's make it work with any number and plus you do not have to pass an array (you can if you still insist). Ok, Enough talk, Let's fight!
The natural solution would be to use arr.join method:
function hash() {
return arguments.join();
}
hash(1,2,4,..); // Error: arguments.join is not a function
Oh, man. Unfortunately, that won’t work. Because we are calling hash(arguments) and arguments object is both iterable and array-like, but not a real array. How about the below approach?
function hash() {
return [].join.call(arguments);
}
hash(1,2,3,4); // "1,2,3,4" whoaa
The trick is called method borrowing.
We borrow a join method from a regular array [].join. And use [].join.call to run it in the context of arguments.
Why does it work?
That’s because the internal algorithm of the native method arr.join(glue) is very simple.
Taken from the specification almost “as-is”:
Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
…Do so until this.length items are glued.
Return result.
So, technically it takes this and joins this[0], this[1] …etc together. It’s intentionally written in a way that allows any array-like this (not a coincidence, many methods follow this practice). That’s why it also works with this=arguments.

There's a better way using JSON not an Array!
// Call a function with a Json Key / Value Pair:
sendMail({param1: p1, param2: p2});
// Function definition and usage of value pairs:
function sendMail(data){
var parameter1 = data.param1;
var parameter2 = data.param2;
}

Related

Array spread alternative for Internet Explorer [duplicate]

I'd like to call a function using an array as parameters:
const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it
function call_me (param0, param1, param2 ) {
// ...
}
Is there a better way of passing the contents of x into call_me()?
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);
See MDN docs for Function.prototype.apply().
If the environment supports ECMAScript 6, you can use a spread argument instead:
call_me(...args);
Why don't you pass the entire array and process it as needed inside the function?
var x = [ 'p0', 'p1', 'p2' ];
call_me(x);
function call_me(params) {
for (i=0; i<params.length; i++) {
alert(params[i])
}
}
In ES6 standard there is a new spread operator ... which does exactly that.
call_me(...x)
It is supported by all major browsers except for IE.
The spread operator can do many other useful things, and the linked documentation does a really good job at showing that.
Assuming that call_me is a global function, so you don't expect this to be set.
var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);
As #KaptajnKold had answered
var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);
And you don't need to define every parameters for call_me function either.
You can just use arguments
function call_me () {
// arguments is a array consisting of params.
// arguments[0] == 'p0',
// arguments[1] == 'p1',
// arguments[2] == 'p2'
}
While using spread operator we must note that it must be the last or only parameter passed. Else it will fail.
function callMe(...arr){ //valid arguments
alert(arr);
}
function callMe(name, ...arr){ //valid arguments
alert(arr);
}
function callMe(...arr, name){ //invalid arguments
alert(arr);
}
If you need to pass an array as the starting argument you can do:
function callMe(arr, name){
let newArr = [...arr];
alert(newArr);
}
Function arguments may also be Arrays:
function foo([a,b,c], d){
console.log(a,b,c,d);
}
foo([1,2,3], 4)
of-course one can also use spread:
function foo(a, b, c, d){
console.log(a, b, c, d);
}
foo(...[1, 2, 3], 4)
Note this
function FollowMouse() {
for(var i=0; i< arguments.length; i++) {
arguments[i].style.top = event.clientY+"px";
arguments[i].style.left = event.clientX+"px";
}
};
//---------------------------
html page
<body onmousemove="FollowMouse(d1,d2,d3)">
<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>
</body>
can call function with any Args
<body onmousemove="FollowMouse(d1,d2)">
or
<body onmousemove="FollowMouse(d1)">
you can use the spread syntax
for example:
function print(...inpu){
console.log(...inpu)
}
var arry = ['p0','p1','p2']
print(...arry)
here is the link: modzilla spread syntax refrence document
you can use spread operator in a more basic form
[].concat(...array)
in the case of functions that return arrays but are expected to pass as arguments
Example:
function expectArguments(...args){
return [].concat(...args);
}
JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))
The answer was already given, but I just want to give my piece of cake. What you want to achieve is called method borrowing in the context of JS, that when we take a method from an object and call it in the context of another object. It is quite common to take array methods and apply them to arguments. Let me give you an example.
So we have "super" hashing function which takes two numbers as an argument and returns "super safe" hashed string:
function hash() {
return arguments[0]+','+arguments[1];
}
hash(1,2); // "1,2" whoaa
So far so good, but we have little problem with the above approach, it is constrained, only works with two numbers, that is not dynamic, let's make it work with any number and plus you do not have to pass an array (you can if you still insist). Ok, Enough talk, Let's fight!
The natural solution would be to use arr.join method:
function hash() {
return arguments.join();
}
hash(1,2,4,..); // Error: arguments.join is not a function
Oh, man. Unfortunately, that won’t work. Because we are calling hash(arguments) and arguments object is both iterable and array-like, but not a real array. How about the below approach?
function hash() {
return [].join.call(arguments);
}
hash(1,2,3,4); // "1,2,3,4" whoaa
The trick is called method borrowing.
We borrow a join method from a regular array [].join. And use [].join.call to run it in the context of arguments.
Why does it work?
That’s because the internal algorithm of the native method arr.join(glue) is very simple.
Taken from the specification almost “as-is”:
Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
…Do so until this.length items are glued.
Return result.
So, technically it takes this and joins this[0], this[1] …etc together. It’s intentionally written in a way that allows any array-like this (not a coincidence, many methods follow this practice). That’s why it also works with this=arguments.
There's a better way using JSON not an Array!
// Call a function with a Json Key / Value Pair:
sendMail({param1: p1, param2: p2});
// Function definition and usage of value pairs:
function sendMail(data){
var parameter1 = data.param1;
var parameter2 = data.param2;
}

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));

Is there a way to provide named parameters in a function call in JavaScript?

I find the named parameters feature in C# quite useful in some cases.
calculateBMI(70, height: 175);
What can I use if I want this in JavaScript?
What I don’t want is this:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
That approach I’ve already used. Is there another way?
I’m okay using any library to do this.
ES2015 and later
In ES2015, parameter destructuring can be used to simulate named parameters. It would require the caller to pass an object, but you can avoid all of the checks inside the function if you also use default parameters:
myFunction({ param1 : 70, param2 : 175});
function myFunction({param1, param2}={}){
// ...function body...
}
// Or with defaults,
function myFunc({
name = 'Default user',
age = 'N/A'
}={}) {
// ...function body...
}
ES5
There is a way to come close to what you want, but it is based on the output of Function.prototype.toString [ES5], which is implementation dependent to some degree, so it might not be cross-browser compatible.
The idea is to parse the parameter names from the string representation of the function so that you can associate the properties of an object with the corresponding parameter.
A function call could then look like
func(a, b, {someArg: ..., someOtherArg: ...});
where a and b are positional arguments and the last argument is an object with named arguments.
For example:
var parameterfy = (function() {
var pattern = /function[^(]*\(([^)]*)\)/;
return function(func) {
// fails horribly for parameterless functions ;)
var args = func.toString().match(pattern)[1].split(/,\s*/);
return function() {
var named_params = arguments[arguments.length - 1];
if (typeof named_params === 'object') {
var params = [].slice.call(arguments, 0, -1);
if (params.length < args.length) {
for (var i = params.length, l = args.length; i < l; i++) {
params.push(named_params[args[i]]);
}
return func.apply(this, params);
}
}
return func.apply(null, arguments);
};
};
}());
Which you would use as:
var foo = parameterfy(function(a, b, c) {
console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
});
foo(1, 2, 3); // a is 1 | b is 2 | c is 3
foo(1, {b:2, c:3}); // a is 1 | b is 2 | c is 3
foo(1, {c:3}); // a is 1 | b is undefined | c is 3
foo({a: 1, c:3}); // a is 1 | b is undefined | c is 3
DEMO
There are some drawbacks to this approach (you have been warned!):
If the last argument is an object, it is treated as a "named argument objects"
You will always get as many arguments as you defined in the function, but some of them might have the value undefined (that's different from having no value at all). That means you cannot use arguments.length to test how many arguments have been passed.
Instead of having a function creating the wrapper, you could also have a function which accepts a function and various values as arguments, such as
call(func, a, b, {posArg: ... });
or even extend Function.prototype so that you could do:
foo.execute(a, b, {posArg: ...});
No - the object approach is JavaScript's answer to this. There is no problem with this provided your function expects an object rather than separate params.
Lots of people say to just use the "Pass an object" trick so that you have named parameters.
/**
* My Function
*
* #param {Object} arg1 Named arguments
*/
function myFunc(arg1) { }
myFunc({ param1 : 70, param2 : 175});
And that works great, except... when it comes to most IDEs out there, a lot of us developers rely on type / argument hints within our IDE. I personally use PhpStorm (along with other JetBrains IDEs, like PyCharm for Python and AppCode for Objective-C).
And the biggest problem with using the "Pass an object" trick is that when you are calling the function, the IDE gives you a single type hint and that's it... How are we supposed to know what parameters and types should go into the arg1 object?
So... the "Pass an object" trick doesn't work for me... It actually causes more headaches with having to look at each function's docblock before I know what parameters the function expects.... Sure, it's great for when you are maintaining existing code, but it's horrible for writing new code.
Well, this is the technique I use... Now, there may be some issues with it, and some developers may tell me I'm doing it wrong, and I have an open mind when it comes to these things... I am always willing to look at better ways of accomplishing a task... So, if there is an issue with this technique, then comments are welcome.
/**
* My Function
*
* #param {string} arg1 Argument 1
* #param {string} arg2 Argument 2
*/
function myFunc(arg1, arg2) { }
var arg1, arg2;
myFunc(arg1='Param1', arg2='Param2');
This way, I have the best of both worlds. New code is easy to write as my IDE gives me all the proper argument hints. And, while maintaining code later on, I can see at a glance, not only the value passed to the function, but also the name of the argument. The only overhead I see is declaring your argument names as local variables to keep from polluting the global namespace. Sure, it's a bit of extra typing, but it's trivial compared to the time it takes to look up docblocks while writing new code or maintaining existing code.
Update - 2022
JavaScript now has the ability to have something close to named parameters using object destructuring available in ES6. Most newer browsers can use this feature See browser support
This is how it works:
// Define your function like this
function myFunc({arg1, arg2, arg3}) {
// Function body
}
// Call your function like this
myFunc({arg1: "value1", arg2: "value2", arg3: "value3"})
// You can also have default values for arguments
function myFunc2({firstName, lastName, age = 21}) {
// Function body
}
// And you can call it with or without an "age" argument
myFunc({firstName: "John", lastName: "Doe"}) // Age will be 21
myFunc({firstName: "Jane", lastName: "Doe", age: 22})
The best part is that most IDE's now support this syntax and you get good argument hint support
TypeScript
For those of you using TypeScript, you can do the same thing using this syntax
function myFunc(
{firstName, lastName, age = 21}:
{firstName: string, lastName: string, age?: number}
) {
// Function body
}
OR, using an interface
interface Params {
firstName: string
lastName: string
age?: number
}
function myFunc({firstName, lastName, age = 21}: Params) {
// Function body
}
If you want to make it clear what each of the parameters are, rather than just calling
someFunction(70, 115);
do the following:
var width = 70, height = 115;
someFunction(width, height);
Sure, it's an extra line of code, but it wins on readability.
Another way would be to use attributes of a suitable object, e.g. like so:
function plus(a,b) { return a+b; };
Plus = { a: function(x) { return { b: function(y) { return plus(x,y) }}},
b: function(y) { return { a: function(x) { return plus(x,y) }}}};
sum = Plus.a(3).b(5);
Of course for this made up example it is somewhat meaningless. But in cases where the function looks like
do_something(some_connection_handle, some_context_parameter, some_value)
it might be more useful. It also could be combined with "parameterfy" idea to create such an object out of an existing function in a generic way. That is for each parameter it would create a member that can evaluate to a partial evaluated version of the function.
This idea is of course related to Schönfinkeling aka Currying.
Calling function f with named parameters passed as the object
o = {height: 1, width: 5, ...}
is basically calling its composition f(...g(o)) where I am using the spread syntax and g is a "binding" map connecting the object values with their parameter positions.
The binding map is precisely the missing ingredient, that can be represented by the array of its keys:
// map 'height' to the first and 'width' to the second param
binding = ['height', 'width']
// take binding and arg object and return aray of args
withNamed = (bnd, o) => bnd.map(param => o[param])
// call f with named args via binding
f(...withNamed(binding, {hight: 1, width: 5}))
Note the three decoupled ingredients: the function, the object with named arguments and the binding. This decoupling allows for a lot of flexibility to use this construct, where the binding can be arbitrarily customized in function's definition and arbitrarily extended at the function call time.
For instance, you may want to abbreviate height and width as h and w inside your function's definition, to make it shorter and cleaner, while you still want to call it with full names for clarity:
// use short params
f = (h, w) => ...
// modify f to be called with named args
ff = o => f(...withNamed(['height', 'width'], o))
// now call with real more descriptive names
ff({height: 1, width: 5})
This flexibility is also more useful for functional programming, where functions can be arbitrarily transformed with their original param names getting lost.
There is another way. If you're passing an object by reference, that object's properties will appear in the function's local scope. I know this works for Safari (haven't checked other browsers) and I don't know if this feature has a name, but the below example illustrates its use.
Although in practice I don't think that this offers any functional value beyond the technique you're already using, it's a little cleaner semantically. And it still requires passing a object reference or an object literal.
function sum({ a:a, b:b}) {
console.log(a+'+'+b);
if(a==undefined) a=0;
if(b==undefined) b=0;
return (a+b);
}
// will work (returns 9 and 3 respectively)
console.log(sum({a:4,b:5}));
console.log(sum({a:3}));
// will not work (returns 0)
console.log(sum(4,5));
console.log(sum(4));
Coming from Python this bugged me. I wrote a simple wrapper/Proxy for node that will accept both positional and keyword objects.
https://github.com/vinces1979/node-def/blob/master/README.md
NB. My answer of 2016 is not correct and misleading as mentioned in comments.
Trying Node-6.4.0 ( process.versions.v8 = '5.0.71.60') and Node Chakracore-v7.0.0-pre8 and then Chrome-52 (V8=5.2.361.49), I've noticed that named parameters are almost implemented, but that order has still precedence. I can't find what the ECMA standard says.
>function f(a=1, b=2){ console.log(`a=${a} + b=${b} = ${a+b}`) }
> f()
a=1 + b=2 = 3
> f(a=5)
a=5 + b=2 = 7
> f(a=7, b=10)
a=7 + b=10 = 17
But order is required!! Is it the standard behaviour?
> f(b=10)
a=10 + b=2 = 12
This is admittedly pseudocode, but I believe it'll work (I know it works in TypeScript; I'm adopting it for JavaScript).
// Target Function
const myFunc = (a=1,b=2,c=3) => {a+b+c}
// Goal usage:
myFunc(a=5, b=6) // 14
myFunc(c=0) // 3
// Set your defaults
const myFuncDefaults = {a:1, b:2, c:3};
// Override them with passed parameters
const myFuncParams = (params) => { return Object.assign(myFuncDefaults, params)}
// Use the overloaded dict as the input
const myFunc2 = (params) => {
let {a, b, c} = myFuncParams(params);
return myFunc(a, b, c)
}
// Usage:
myFunc({a:5, b:6}) // 14
myFunc({c:0}) // 3
// Written more succinctly:
const myFunc = (params) => {
let {a,b,c} = Object.assign({a:1, b:2, c:3}, params)
return a + b + c
}
For what it's worth, TypeScript makes this kind of nice with hinting:
interface IParams {
a: number;
b: number;
c: number;
}
const myFunc = (params: Partial<IParams>): number => {
const default: IParams = {a:1, b:2, c:3};
let {a, b, c} = Object.assign(default, params)
return a + b + c
}
Yes, well, kind of. I've found two solutions. I'll explain just one.
In this solution, we give up positional arguments, though.
We can use an object (almost identical to a dict in Python) to pass the arguments.
In this example, I'm using the function to generate the name of a image file:
// First we define our function with just ONE argument
function name_of_img(img_desc){
// With this step, any undefined value will be assigned a value
if(img_desc.size == undefined) {img_desc.size = "400x500"}
if(img_desc.format == undefined) {img_desc.format = ".png"}
console.log(img_desc.size + img_desc.format)
}
// Notice inside our function we're passing a dict/object
name_of_img({size: "200x250", format : ".jpg"})
// In Python name_of_img(size="200x250" , format="jpg")
// returns "200x250.jpg"
name_of_img({size: "1200x950"})
// In Python name_of_img(size="1200x950")
// returns "1200x950.png"
We can modify this example, so we can use positional arguments too, we can also modify it so non valid arguments can be passed, I think I will make a GitHub repository about this.
Contrary to what is commonly believed, named parameters can be implemented in standard, old-school JavaScript (for boolean parameters only) by means of a simple, neat coding convention, as shown below.
function f(p1=true, p2=false) {
...
}
f(!!"p1"==false, !!"p2"==true); // call f(p1=false, p2=true)
Caveats:
Ordering of arguments must be preserved - but the pattern is still useful, since it makes it obvious which actual argument is meant for which formal parameter without having to grep for the function signature or use an IDE.
This only works for booleans. However, I'm sure a similar pattern could be developed for other types using JavaScript's unique type coercion semantics.

Is there a JavaScript equivalent for C# 'params'?

I need a method that can have an arbitrary number of parameters. In C# we have the params statement. Do we have anything similar in JavaScript?
There is the arguments collection, which contains all arguments passed to the function.
There is a) no need to specify "optional" arguments in the function signature and b) any function accepts any number of parameters.
function foo() {
console.log(arguments);
}
foo(1,2,3,4); // logs [1, 2, 3, 4]
Likewise, there is no need to supply "required" arguments in a function call:
function foo(a, b, c, d) {
console.log(arguments);
}
foo(1,2); // logs [1, 2]
Any argument named in the signature but not supplied in the function call will be undefined.
Note that arguments behaves like an Array, but technically it isn't one. For example, you can call arguments[0], but you can't call arguments.slice(). What you can do to get around this is using the Array prototype:
Array.prototype.slice.call(arguments, 1, 2);
The so-called rest parameter ... is a new (ES6+) addition to the language and makes working with variadic functions more comfortable. #ArunCM's answer explains it.
I know this thread is too old but I believe something is missing here.
There is Rest parameter (introduced in ECMAScript 6) which will allow us to represent an indefinite number of arguments as an array.
It always returns an array. Which means even in defensive JavaScript land, it’s ok to do things like check .length of rest without guards.
Syntax :
function(a, b, ...theArgs) {
// ...
}
There are three main differences between rest parameters and the arguments object:
rest parameters are only the ones that haven't been given a separate name, while the arguments object contains all arguments passed to the function
the arguments object is not a real array, while rest parameters are Array instances, meaning methods like sort, map, forEach or pop can be applied on it directly;
the arguments object has additional functionality specific to itself (like the callee property).
Additional reading : Spread
function f(x, ...y) {
// y is an Array
return x * y.length;
}
console.log("Expected result : 3*2 = 6 & Actual result : " + f(3, "hello", true));
console.log("Expected result : 3*4 = 12 & Actual result : " + f(3, "a", true, "b", 1));
//here we are not passing anything to "y" but its still safe to check .length of "y" because it always return an array.
console.log("Expected result : 3*0 = 0 & Actual result : " + f(3));
Yes. arguments.
function concatStrings () {
var str = '';
for (var i = 0; i < arguments.length; i++) {
str += arguments[i];
}
return str;
}
Be aware that arguments isn't an array, so it doesn't have methods like join or push. It's just an array-like object (with numerical properties and a length property) so it can be iterated through.
JavaScript has arguments object inside functions. It contains of all params passed to the function.
More info
It is some sort of implicit in the special variable "arguments". Use like this:
function something(arg1, arg2) {
for (var i = 0; i < arguments.length; i++) {
var x = arguments[i];
}
}
Then you can call it like something(1, 2, 3, 'a', 'b', 'c')
More examples here: http://www.jtricks.com/javascript_tutorials/varargs.html
Javascript functions can accept any number of parameters by default. You can see them with the arguments variable.
See here.

What is the difference between call and apply?

What is the difference between using Function.prototype.apply() and Function.prototype.call() to invoke a function?
var func = function() {
alert('hello!');
};
func.apply(); vs func.call();
Are there performance differences between the two aforementioned methods? When is it best to use call over apply and vice versa?
The difference is that apply lets you invoke the function with arguments as an array; call requires the parameters be listed explicitly. A useful mnemonic is "A for array and C for comma."
See MDN's documentation on apply and call.
Pseudo syntax:
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
There is also, as of ES6, the possibility to spread the array for use with the call function, you can see the compatibilities here.
Sample code:
function theFunction(name, profession) {
console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator
K. Scott Allen has a nice writeup on the matter.
Basically, they differ on how they handle function arguments.
The apply() method is identical to call(), except apply() requires an array as the second parameter. The array represents the arguments for the target method."
So:
// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
To answer the part about when to use each function, use apply if you don't know the number of arguments you will be passing, or if they are already in an array or array-like object (like the arguments object to forward your own arguments. Use call otherwise, since there's no need to wrap the arguments in an array.
f.call(thisObject, a, b, c); // Fixed number of arguments
f.apply(thisObject, arguments); // Forward this function's arguments
var args = [];
while (...) {
args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments
When I'm not passing any arguments (like your example), I prefer call since I'm calling the function. apply would imply you are applying the function to the (non-existent) arguments.
There shouldn't be any performance differences, except maybe if you use apply and wrap the arguments in an array (e.g. f.apply(thisObject, [a, b, c]) instead of f.call(thisObject, a, b, c)). I haven't tested it, so there could be differences, but it would be very browser specific. It's likely that call is faster if you don't already have the arguments in an array and apply is faster if you do.
Here's a good mnemonic. Apply uses Arrays and Always takes one or two Arguments. When you use Call you have to Count the number of arguments.
While this is an old topic, I just wanted to point out that .call is slightly faster than .apply. I can't tell you exactly why.
See jsPerf, http://jsperf.com/test-call-vs-apply/3
[UPDATE!]
Douglas Crockford mentions briefly the difference between the two, which may help explain the performance difference... http://youtu.be/ya4UHuXNygM?t=15m52s
Apply takes an array of arguments, while Call takes zero or more individual parameters! Ah hah!
.apply(this, [...])
.call(this, param1, param2, param3, param4...)
Follows an extract from Closure: The Definitive Guide by Michael Bolin. It might look a bit lengthy, but it's saturated with a lot of insight. From "Appendix B. Frequently Misunderstood JavaScript Concepts":
What this Refers to When a Function is Called
When calling a function of the form foo.bar.baz(), the object foo.bar is referred to as the receiver. When the function is called, it is the receiver that is used as the value for this:
var obj = {};
obj.value = 10;
/** #param {...number} additionalValues */
obj.addValues = function(additionalValues) {
for (var i = 0; i < arguments.length; i++) {
this.value += arguments[i];
}
return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);
If there is no explicit receiver when a function is called, then the global object becomes the receiver. As explained in "goog.global" on page 47, window is the global object when JavaScript is executed in a web browser. This leads to some surprising behavior:
var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN
Even though obj.addValues and f refer to the same function, they behave differently when called because the value of the receiver is different in each call. For this reason, when calling a function that refers to this, it is important to ensure that this will have the correct value when it is called. To be clear, if this were not referenced in the function body, then the behavior of f(20) and obj.addValues(20) would be the same.
Because functions are first-class objects in JavaScript, they can have their own methods. All functions have the methods call() and apply() which make it possible to redefine the receiver (i.e., the object that this refers to) when calling the function. The method signatures are as follows:
/**
* #param {*=} receiver to substitute for 'this'
* #param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* #param {*=} receiver to substitute for 'this'
* #param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;
Note that the only difference between call() and apply() is that call() receives the function parameters as individual arguments, whereas apply() receives them as a single array:
// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);
The following calls are equivalent, as f and obj.addValues refer to the same function:
obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);
However, since neither call() nor apply() uses the value of its own receiver to substitute for the receiver argument when it is unspecified, the following will not work:
// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);
The value of this can never be null or undefined when a function is called. When null or undefined is supplied as the receiver to call() or apply(), the global object is used as the value for receiver instead. Therefore, the previous code has the same undesirable side effect of adding a property named value to the global object.
It may be helpful to think of a function as having no knowledge of the variable to which it is assigned. This helps reinforce the idea that the value of this will be bound when the function is called rather than when it is defined.
End of extract.
It is useful at times for one object to borrow the function of another object, meaning that the borrowing object simply executes the lent function as if it were its own.
A small code example:
var friend = {
car: false,
lendCar: function ( canLend ){
this.car = canLend;
}
};
var me = {
car: false,
gotCar: function(){
return this.car === true;
}
};
console.log(me.gotCar()); // false
friend.lendCar.call(me, true);
console.log(me.gotCar()); // true
friend.lendCar.apply(me, [false]);
console.log(me.gotCar()); // false
These methods are very useful for giving objects temporary functionality.
Another example with Call, Apply and Bind.
The difference between Call and Apply is evident, but Bind works like this:
Bind returns an instance of a function that can be executed
First Parameter is 'this'
Second parameter is a Comma separated list of arguments (like Call)
}
function Person(name) {
this.name = name;
}
Person.prototype.getName = function(a,b) {
return this.name + " " + a + " " + b;
}
var reader = new Person('John Smith');
reader.getName = function() {
// Apply and Call executes the function and returns value
// Also notice the different ways of extracting 'getName' prototype
var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);
console.log("Apply: " + baseName);
var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy");
console.log("Call: " + baseName);
// Bind returns function which can be invoked
var baseName = Person.prototype.getName.bind(this, "is a", "boy");
console.log("Bind: " + baseName());
}
reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/
I'd like to show an example, where the 'valueForThis' argument is used:
Array.prototype.push = function(element) {
/*
Native code*, that uses 'this'
this.put(element);
*/
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9]
**details: http://es5.github.io/#x15.4.4.7*
Call() takes comma-separated arguments, ex:
.call(scope, arg1, arg2, arg3)
and apply() takes an array of arguments, ex:
.apply(scope, [arg1, arg2, arg3])
here are few more usage examples:
http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/
From the MDN docs on Function.prototype.apply() :
The apply() method calls a function with a given this value and
arguments provided as an array (or an array-like object).
Syntax
fun.apply(thisArg, [argsArray])
From the MDN docs on Function.prototype.call() :
The call() method calls a function with a given this value and arguments provided individually.
Syntax
fun.call(thisArg[, arg1[, arg2[, ...]]])
From Function.apply and Function.call in JavaScript :
The apply() method is identical to call(), except apply() requires an
array as the second parameter. The array represents the arguments for
the target method.
Code example :
var doSomething = function() {
var arr = [];
for(i in arguments) {
if(typeof this[arguments[i]] !== 'undefined') {
arr.push(this[arguments[i]]);
}
}
return arr;
}
var output = function(position, obj) {
document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}
output(1, doSomething(
'one',
'two',
'two',
'one'
));
output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
'one',
'two',
'two',
'one'
]));
output(3, doSomething.call({one : 'Steven', two : 'Jane'},
'one',
'two',
'two',
'one'
));
See also this Fiddle.
Here's a small-ish post, I wrote on this:
http://sizeableidea.com/call-versus-apply-javascript/
var obj1 = { which : "obj1" },
obj2 = { which : "obj2" };
function execute(arg1, arg2){
console.log(this.which, arg1, arg2);
}
//using call
execute.call(obj1, "dan", "stanhope");
//output: obj1 dan stanhope
//using apply
execute.apply(obj2, ["dan", "stanhope"]);
//output: obj2 dan stanhope
//using old school
execute("dan", "stanhope");
//output: undefined "dan" "stanhope"
Fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.
The difference is that call() takes the function arguments separately, and apply() takes the function arguments in an array.
Summary:
Both call() and apply() are methods which are located on Function.prototype. Therefore they are available on every function object via the prototype chain. Both call() and apply() can execute a function with a specified value of the this.
The main difference between call() and apply() is the way you have to pass in arguments into it. In both call() and apply() you pass as a first argument the object you want to be the value as this. The other arguments differ in the following way:
With call() you have to put in the arguments normally (starting from the second argument)
With apply() you have to pass in array of arguments.
Example:
let obj = {
val1: 5,
val2: 10
}
const summation = function (val3, val4) {
return this.val1 + this.val2 + val3 + val4;
}
console.log(summation.apply(obj, [2 ,3]));
// first we assign we value of this in the first arg
// with apply we have to pass in an array
console.log(summation.call(obj, 2, 3));
// with call we can pass in each arg individually
Why would I need to use these functions?
The this value can be tricky sometimes in javascript. The value of this determined when a function is executed not when a function is defined. If our function is dependend on a right this binding we can use call() and apply() to enforce this behaviour. For example:
var name = 'unwantedGlobalName';
const obj = {
name: 'Willem',
sayName () { console.log(this.name);}
}
let copiedMethod = obj.sayName;
// we store the function in the copiedmethod variable
copiedMethod();
// this is now window, unwantedGlobalName gets logged
copiedMethod.call(obj);
// we enforce this to be obj, Willem gets logged
We can differentiate call and apply methods as below
CALL : A function with argument provide individually.
If you know the arguments to be passed or there are no argument to pass you can use call.
APPLY : Call a function with argument provided as an array. You can use apply if you don't know how many argument are going to pass to the function.
There is a advantage of using apply over call, we don't need to change the number of argument only we can change a array that is passed.
There is not big difference in performance. But we can say call is bit faster as compare to apply because an array need to evaluate in apply method.
The main difference is, using call, we can change the scope and pass arguments as normal, but apply lets you call it using arguments as an Array (pass them as an array). But in terms of what they to do in your code, they are pretty similar.
While the syntax of this function is almost identical to that of
apply(), the fundamental difference is that call() accepts an argument
list, while apply() accepts a single array of arguments.
So as you see, there is not a big difference, but still, there are cases we prefer using call() or apply(). For example, look at the code below, which finding the smallest and largest number in an array from MDN, using the apply method:
// min/max number in an array
var numbers = [5, 6, 2, 3, 7];
// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers);
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)
var min = Math.min.apply(null, numbers)
So the main difference is just the way we passing the arguments:
Call:
function.call(thisArg, arg1, arg2, ...);
Apply:
function.apply(thisArg, [argsArray]);
Difference between these to methods are, how you want to pass the parameters.
“A for array and C for comma” is a handy mnemonic.
Call and apply both are used to force the this value when a function is executed. The only difference is that call takes n+1 arguments where 1 is this and 'n' arguments. apply takes only two arguments, one is this the other is argument array.
The advantage I see in apply over call is that we can easily delegate a function call to other function without much effort;
function sayHello() {
console.log(this, arguments);
}
function hello() {
sayHello.apply(this, arguments);
}
var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');
Observe how easily we delegated hello to sayHello using apply, but with call this is very difficult to achieve.
Even though call and apply achive the same thing, I think there is atleast one place where you cannot use call but can only use apply. That is when you want to support inheritance and want to call the constructor.
Here is a function allows you to create classes which also supports creating classes by extending other classes.
function makeClass( properties ) {
var ctor = properties['constructor'] || function(){}
var Super = properties['extends'];
var Class = function () {
// Here 'call' cannot work, only 'apply' can!!!
if(Super)
Super.apply(this,arguments);
ctor.apply(this,arguments);
}
if(Super){
Class.prototype = Object.create( Super.prototype );
Class.prototype.constructor = Class;
}
Object.keys(properties).forEach( function(prop) {
if(prop!=='constructor' && prop!=='extends')
Class.prototype[prop] = properties[prop];
});
return Class;
}
//Usage
var Car = makeClass({
constructor: function(name){
this.name=name;
},
yourName: function() {
return this.name;
}
});
//We have a Car class now
var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat
var SuperCar = makeClass({
constructor: function(ignore,power){
this.power=power;
},
extends:Car,
yourPower: function() {
return this.power;
}
});
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6
Let me add a little detail to this.
these two calls are almost equivalent:
func.call(context, ...args); // pass an array as list with spread operator
func.apply(context, args); // is same as using apply
There’s only a minor difference:
The spread operator ... allows passing iterable args as the list to call.
The apply accepts only array-like args.
So, these calls complement each other. Where we expect an iterable, call works, where we expect an array-like, apply works.
And for objects that are both iterable and array-like, like a real array, we technically could use any of them, but apply will probably be faster because most JavaScript engines internally optimize it better.
I just want to add a simple example to a well explained post by flatline, which makes it easy to understand for beginners.
func.call(context, args1, args2 ); // pass arguments as "," separated value
func.apply(context, [args1, args2]); // pass arguments as "Array"
we also use "Call" and "Apply" method for changing reference as defined in code below
let Emp1 = {
name: 'X',
getEmpDetail: function(age, department) {
console.log(`Name: ${this.name} Age: ${age} Department: ${department}`)
}
}
Emp1.getEmpDetail(23, 'Delivery')
// 1st approach of changing "this"
let Emp2 = {
name: 'Y',
getEmpDetail: Emp1.getEmpDetail
}
Emp2.getEmpDetail(55, 'Finance')
// 2nd approach of changing "this" using "Call" and "Apply"
let Emp3 = {
name: 'Emp3_Object',
}
Emp1.getEmpDetail.call(Emp3, 30, 'Admin')
// here we have change the ref from **Emp1 to Emp3** object
// now this will print "Name = Emp3_Object" because it is pointing to Emp3 object
Emp1.getEmpDetail.apply(Emp3, [30, 'Admin'])
The call() method calls a function with a given this value and a second parameter which are arguments separated by comma.
object.someMethod.call( someObject, arguments )
The apply() method is the same as call except the fact that the second argument it takes is an array of arguments .
object.someMethod.apply( someObject, arrayOfarguments )
var car = {
name: "Reno",
country: "France",
showBuyer: function(firstName, lastName) {
console.log(`${firstName} ${lastName} just bought a ${this.name} from ${this.country}`);
}
}
const firstName = "Bryan";
const lastName = "Smith";
car.showBuyer(firstName, lastName); // Bryan just bought a Reno from France
const obj = { name: "Maserati", country: "Italy" };
car.showBuyer.call(obj, firstName, lastName); // Bryan Smith just bought a Maserati from Italy
car.showBuyer.apply(obj, [firstName, lastName]); // Bryan Smith just bought a Maserati from Italy

Categories

Resources