For example,
var listToBecomeArguments = ["foo","bla"];
myFunc(listToBecomeArguments);
when called would do something like this:
function myFunc(arg1, arg2) {
// arg1 is "foo", arg2 is "bla"
}
For your function
function myFunc(arg1, arg2) {...}
use the .apply() method like this:
myFunc.apply(null, listToBecomeArguments);
and it will do the same as this:
myFunc(listToBecomeArguments[0], listToBecomeArguments[1],...);
You could use local variable arguments to do what you want.
function myFunc() {
console.log(arguments);
}
myFunc("param1", "param2");
// Output:
// > ["param1","param2"]
Quoting the MDN article above, arguments is
an Array-like object corresponding to the arguments passed to a function.
Related
I have an object of arbitrary functions and a function that takes a method name and an object or an array with parameters and then selects and calls the function accordingly. The problem is that functions have a variable number of inputs and some of them contain optional fields with default values and I can't find a general way to map inputs of the parameters to inputs of the function.
One way to solve the problem when the arguments come in the form of the array is just simply called the function with the ... operator: func(...args), but that still leaves me with a problem, because I can't use these methods on objects. Is there any way to map object values to function inputs by using object keys?
Abstract example of the situation:
const funcs = {
func1: (arg1, arg2, arg3 = 'something') => .....does something
func2: () => ....does something
func3: (anotherArg1) => ...does something
}
function callFunction(method: string, args: unknown[]| object) {
if (Array.isArray(args)) {
return funcs[method](...args)
}
else (if args instanceof Object) {
//... Here I need to parse the args and call the function in "funcs" object.
}
}
Just spread the second argument of callFunction(method, ...args)
const funcs = {
func1: (arg1, arg2, arg3 = 'something') => {
[arg1, arg2, arg3].forEach((a, i) => console.log(`arg${i+1}:`, JSON.stringify(a)));
}
}
function callFunction(method, ...args) {
return funcs[method](...args)
}
const method = 'func1';
callFunction(method, [1, 2], {foo: 'bar'})
I have found a script example, in it there is a line of code that looks something like this:
fn = (arg1) => (arg2) => {
//do something with arg1 and arg2
}
I am wondering exactly what is happening here, and how would it look as a "normal" function?
fn = (arg1) => (arg2) => {
//do something with arg1 and arg2
}
fn is a name for the first anon function
its basically a function that returns another function
it translated roughly to
var fn = function(arg1){
return function(arg2){
... // do something
}
}
noting that the this value will differ because it is an arrow function .
It looks like two nested function, where the outer function returns the inner function with a closure over arg1.
var fn = function (arg1) {
return function (arg2) {
//do something with arg1 and arg2
};
};
var fn = function (arg1) {
return function (arg2) {
return arg1 + arg2;
};
};
var add4 = fn(4),
add20 = fn(20);
console.log(add4(5)); // 9
console.log(add20(5)); // 25
Arrow function:
An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.
I cannot add comments so I write this as an answer. Your example is also known as currying a concept that allows you to pass in a subset of arguments to a function and get a function back that’s waiting for the rest of the arguments.
Is there a difference whether I use foo.caller.arguments or simple arguments inside function foo:
function foo(){
console.log(foo.caller.arguments);
}
function foo(){
console.log(arguments);
}
As it's said in the comments to the question, caller is not a standard property:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller
Having said that, it returns a reference to the caller, that is, the function that has called the current function. So, caller.arguments gets you the arguments with which the caller has been invoked.
arguments gets you the arguments used in the call to the current function.
For example:
function one(c) {
console.log('arguments', arguments);
console.log('caller.arguments', one.caller.arguments);
}
function two(a, b) {
one(3);
}
two(1, 2)
Prints
arguments [3]
caller.arguments [1, 2]
arguments gives the arguments to the fuction itself whereas caller.arguments gives the arguments of the functions which calls this function. Following code will give you the basic understanding.
BTW function.caller is Non-standard as suggested bt MDN
var foo = function(name) {
bar('second');
}
var bar = function(surname) {
console.log(arguments);
console.log(bar.caller.arguments)
}
foo('first');
javascript beginner here.
Let's say I'm having a javascript function that takes 3 arguments:
function f(arg1, arg2, arg3) { // do stuff }
I know that I can call f(value1, value2); and in that case inside the function scope arg1 will be value1, arg2 will be value2 and arg3 will be null.
Everything ok with this. However if I want to call the function giving values only to arg1 and arg3 I need to do something like this: f(value1, null, value2);
Is there a way I can specify which arguments to have which values in a more C#-esque manner (without specifying not given arguments as null)? Something like this: for calling f with values only for arg1 and arg3 I would write f(value1, arg3 = value2);
Any ideas?
Cheers!
there is a way i have seen for this:
for example
function person(name,surname,age)
{
...
}
person('Xavier',null,30);
you can do this:
function person(paramObj)
{
var name = paramObj.name;
var surname = paramObj.surname;
var age = paramObj.age;
}
calling like this:
person({name:'Xavier',age:30});
I think this is the closest you'll be able to do it like in c# have in mind that JS is not compilled so you can't predict the arguments of a function.
EDIT:
For better syntax you can use ES6 object destructuring, like this:
function person({name, surname, age})
{
...
}
https://javascript.info/destructuring-assignment
Yes you can. It can be written as:
f(arg1, undefined, arg3);
In this call, arguments 1 and 3 will pass, and argument 2 will not be sent.
If you were going to do (let's say it was valid)
f(value1, arg3 = value2)
Then argument 2 would be undefined, so just pass that:
f(value1, undefined, value2)
The only way you would be able to do this with JS is to pass one array containing all of the parameters.
Your default values would have to be set within the function - you can't define default values for arguments in JavaScript.
function foo( args ){
var arg1 = args[ 0 ] || "default_value";
var arg2 = args[ 1 ] || 0;
///etc...
}
Even better, instead of an array you could pass a simple object which would allow you to access the arguments by their key in the object:
function foo( params ){
var arg1 = params[ "arg1" ] || "default_value";
var arg2 = params[ "arg2" ] || 0;
///etc...
}
Hey I had a similar problem but i don't know if it would apply in any context, and if it's the same for ES5, but in ES6 and within my context i was able to just pass undefined as the argument i want to skip.
What i mean by context, is that in my case I am assigning a default value to that argument in the function with ES6 format:
const exampleFunc = (arg1 = "defaultValue",arg2) => {
console.log(arg1,arg2)
}
exampleFunc(undefined,"hello!");
//this would log to the console "defaultValue","hello!"
I'm not sure if this would work if you don't have a default value assigned in the function with ES6 format, but it worked for me! Hope this helped
With ECMAScript 6 (ECMAScript 2015) and the introduction of Default Parameters, it can be as easy as setting default values to the parameters and passing undefined to skip a parameter:
function paramsTest(p1 = "p1 def", p2 = "p2 def", p3 = "p3 def") {
console.log([p1, p2, p3]);
}
paramsTest(); // [ "p1 def", "p2 def", "p3 def"]
paramsTest("p#1", "p#2"); // [ "p#1", "p#2", "p3 def"]
paramsTest("p#1", undefined, null); // [ "p#1", "p2 def", null]
Add this code to your function (for default values)
function f(a, b, c)
{
a = typeof a !== 'undefined' ? a : 42;
b = typeof b !== 'undefined' ? b : 'default_b';
a = typeof c !== 'undefined' ? c : 43;
}
call the function like this
f(arg1 , undefined, arg3)
Another interesting approach to this would be to use the Function.prototype.call() method. All we have to do is assign the arguments with default call object values, and then you're free to call the method with only the arguments you want to use:
function f(arg1 = this.arg1, arg2 = this.arg2 || false, arg3 = this.arg3) {
console.log([arg1, arg2, arg3]);
}
f.call({ arg1: 'value for arg1', arg3: 'value for arg3'});
f('value for arg1', undefined, 'value for arg3');
Notice that I set arg2 to this.arg2 || false - this syntax allows a fallback to false instead of undefined when no f.call instance object arg2 property exists.
in ES6, if your parameters are optional because they have default values and you are okay passing an object, you can use spread syntax:
function f(opts) {
const args = {
arg1: 'a',
arg2: 'b',
arg3: 'c',
...opts
}
const {arg1, arg2, arg3} = args
return arg1.concat(arg2, arg3)
}
f() // "abc"
f({arg1: '1', arg3: '3'}) // "1b3"
f({arg2: ' whatever '}) // "a whatever c"
i came across a situation where I need to call another function with .call() or .apply() like this:
function b() {
alert(arg);
}
Then
function a(arg) {
b.call();
}
a(123);
Function b is called, but doesnt' have access to arg. That's ok, I can pass scope.. yes?
function a(arg) {
b.call(this);
}
a(123);
Still no - I can't access arg from function b. How can I do it?
UPDATE:
I do not want to modify b function :-)
You still need to pass the arguments via call (individually) or apply (as an array):
function a(arg1, arg2, arg3) {
b.call(this, arg1, arg2, arg3);
// or
b.apply(this, arguments)
// or
b.apply(this, [arg1, arg2, arg3]);
}
Of course, nothing about your situation suggests actually using call or apply: Just invoke the function yourself.
function a(arg) {
b(arg);
}
It’s not possible to “pass scope” or something like that. The scope of a function is determined when the function is created, so it can only access arg if it exists where b is defined.
If arg was part of this, then you could do this using call, i.e. make the this in b the same this as it is in a (of course this will modify whatever this actually refers to, which can have side effects you might not want to happen).
function a (arg) {
this.arg = arg;
b.call(this);
}
function b () {
console.log(this.arg);
}
The other way would be to just pass the argument to b as an actual function argument. You can access all arguments of a function using arguments:
function b () {
console.log(arguments);
}
Try this one:
function a(arg) {
b.apply(this, [arg]);
// or
// b.call(this, arg);
}
function b() {
alert(arguments);
}
You failed to pass the arguments when you called b.
Function::call allows you to pass a fixed number of arguments:
function a(arg1,arg2) {
return b.call(this,arg1,arg2);
}
Function::apply allows you to pass any number of arguments, as an array:
function a(arg1,arg2) {
return b.apply(this,[arg1,arg2]);
}
// or
function a(arg1,arg2) {
return b.apply(this,arguments); // The magical 'arguments' variable
}
this is the context object, and is not the same thing as scope.
I'll guess the problem lies in b(). There's no 'arg' argument defined. Try:
function b(arg) { alert(arg); }
and
function a(arg) {
b.call(this,arg);
}
a(123);
now it runs
(Update: the call needs the arguments ( context functionarg1, functionarg2...) )
Assuming that, for some reasons you can't modify the body of b , you can try something like this:
function a(arg) {
eval("("+ b.toString() +")()");
}
DEMO