Pass in any number of arguments into a Javascript function [duplicate] - javascript

This question already has answers here:
JavaScript variable number of arguments to function
(12 answers)
Closed 5 years ago.
I want to be able to pass in any number of arguments into a function and then be able to use those arguments later. I know I can pass in default arguments but I don't know what to declare in my function.
For example,
function test(????) {
console.log(a)
console.log(b)
console.log(c)
}
test(a="a", b="b", c="c")
I'm also challenged by being given this function and to make as little changes to the var declarations as much as possible. So here, variables, a, b, and c are declared and I'm not able to edit these variables. I should be able to pass in arguments that will then know to assign itself to these variables.
function test(???) {
var a,b,c
if (a>b){
c = a + b
}
}
test(a=2,b=3)

You actually don't need to define any arguments in the function parameters. All you need to do is access javascript's built in arguments object.
So your code could look like the following:
function test() {
var a = arguments[0];
var b = arguments[1];
var c = arguments[2];
console.log(a);
console.log(b);
console.log(c);
}
test("a", "b", "c");
For reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments

Using an array is a good idea, but in the interest of completeness...
The ES6 way!
If you're able to support ES6 features, the spread operator combined with the arguments keyword is a neat way to get around that:
function anyNumber() {
console.log(...arguments); // -> 1 2 3 4
let argsAsArray = [0, ...arguments, 5]; // now they're an array
argsAsArray.forEach(s => console.log(s)); // -> 0 1 2 3 4 5
};
anyNumber(1,2,3,4);
There are a lot of cool things you can do with the spread operator, especially with object and parameter destructuring.

you could pass in an object or an array:
function test1([a, b, c]) {
// ...
}
test1([1, 2, 3]);
function test2({ a, b, c }) {
// ...
}
test2({ a: 1, b: 2, c: 3 });

function test(input) {
console.log(input.a);
console.log(input.b);
console.log(input.c);
}
test({ a: 1, b: 2, c: 3 });

You should use an array or an object.
In that array add as many arguments you want.
function test(arr) {
console.log(arr.a);
console.log(arr.b);
console.log(arr.c);
}
arr = {}
arr.a = "a";
arr.b = "b";
arr.c = "c";
k = test(arr);

Given javascript at updated Question, you can define default parameters within () following function name.
function test(a = 2, b = 3) {
let c;
if (a > b) {
c = a + b
} else {
c = 0
}
console.log(c);
}
test(); // 0
test(4); // 7
See also Can we set persistent default parameters which remain set until explicitly changed?

Related

How to pass specified parameters in Javascript

I would like to pass value to specified parameters and use default value by optional parameters for the rest.
A sample is made as below.
Current result is 'b23'.
But I would like to obtain the result of '1b3'.
function runThis() {
test(b='b');
}
function test(a='1',b='2',c='3'){
console.println(a+b+c);
}
I also try to run test({b:'b'}) and test({b:='b'}), resulting SyntaxError.
Thank you for your help.
The syntax is slightly different:
> function test({a=1, b=2, c=3}) { console.log(a+b+c); }
undefined
> test({b:"b"})
1b3
undefined
Parameters are positional in javascript - the first parameter will always be 'a', the second 'b' and so on.
One way to achieve named parameters would be to change the signature of the function test to accept an object:
function test(obj) {
const { a='1', b='2', c='3' } = obj
console.log(a + b + c)
}
Calling this with
test({ b: 'b' })
will yield '1b3'
Keyword arguments are not supported in JS, arguments are resolved by their position in JS.
You could instead pass in an object and destructure the properties from it and also assign default values.
function runThis() {
test({ b: "b" });
}
function test(inputObj) {
const { a = "1", b = "2", c = "3" } = inputObj;
console.log(a + b + c);
}
runThis();
You could also do the destructuring more succinctly, as shown below:
function test({ a = "1", b = "2", c = "3" }) {
console.log(a + b + c);
}
Also, console.println is not a thing in JS, you can use console.log instead.

javascript constructor with optional parameters

I am learning Javascript now and coming from the background of Java. In Java we have overloaded constructors wherein, at compile time, the compiler will decide which version of constructor to be called.
In case of Javascript, we can have only one constructor. In this case, if the constructor has 3 arguments, how to pass only the third parameter.
Ex:
class Addition {
constructor(a,b,c){
console.log(a+B+c);
}
}
Addition obj = new Addition(null, 40, null);
//or
Addition onj2 = new Addition(undefined, undefined, 45);
Is there a better way to do this in Javascript?
You may use EcmaScript's parameter destructuring with default values to achieve that. Additionally, you need to use const (or let, or var) keyword to create variables.
class Addition {
constructor({a = 0, b = 0, c = 0}) {
console.log(a + b + c);
}
}
const obj = new Addition({a: null, b: 40, c: null});
const onj2 = new Addition({c: 45});
There is no possibility of overloading in JS, but you can work with Object destructuring. They can even be complex and refer to other default parameters, like:
function rangeMessage({from=1, to=from+1, message=(counter) => `Hello ${counter}`}={}) {
for(from; from <= to; from++) {
console.log(message(from));
}
}
rangeMessage({from: 10, to: 20});
rangeMessage({to: 10, message:(counter) => `Bye ${counter}`})
rangeMessage()
function sumABC({a=null, b=null, c=null}={}) {
let result = 0;
if(a) result += a;
if(b) result += b;
if(c) result += c;
return result;
}
console.log(sumABC());
console.log(sumABC({a:10}));
console.log(sumABC({b:5}));
console.log(sumABC({b: 10, c: 5}));
The {} = {} part does the same as the other destructuring assignments - if no object was passed in, assume an empty object (which is then filled by the object destructuring statements from the left side).
I hope this solved you question :D
class Addition {
constructor(a=null,b=null,c=null){
console.log(a+b+c);
}
}
var obj = new Addition(null, 40, null);
var onj2 = new Addition(undefined, undefined, 45);

What is this JavaScript construct called

I've found a JavaScript arrow function that looks something like this:
([a,b,c]) => {
a = 1;
b = 2;
c = 'x';
}
How is this function invoked? Also, what is this construct called?
This is an arrow function, which gets an array as a parameter and destruct the first 3 values into the corresponding parameters - a,b,c. But it must be assigned to a variable or be self invoked.
() => {} - Arrow function
[a,b,c] - Array destructuring
Example
const func = ([a,b,c]) => {
console.log(a);
console.log(b);
console.log(c);
};
func([1,2,3,4]);
([a, b, c]) => {}
The first part is a destructuring assignment in the parameters, which takes an array as parameter and returns the variables with the values of the position.
The later assignment makes no sense with the given code.

Number Objects Passed Into Functions by Reference

I was reading somewhere that when we pass an object into a function "...JavaScript always uses the Object by reference when it passes as argument..." What I think this implies is (correct me if I'm wrong) is that if the function was to modify the object in some way, it would change the original defined object. I tried illustrating this with some code and it does do what I think it does but when I try the example in the blog post with a Number obj, it doesn't change the original value in that object. Please see my jsbin: https://jsbin.com/wociro/edit?js,console,output
console.clear();
/**myobject Object**/
function myobject() {
this.value = 5;
}
var o = new myobject();
console.log("Original value of o: " + o.value); // o.value = 5
function objectchanger(fnc) {
fnc.value = 6;
}
objectchanger(o);
console.log("New value of o: " + o.value); // o.value is now equal to 6
/*Number Object*/
var num2 = new Number(2);
console.log("Original value of num2: " + num2);
function numberChanger(fnc) {
return fnc + 1;
}
console.log("num2 after running numberChanger: " + numberChanger(num2));
console.log("New value of num2: " + num2); //looks the same
Am I missing something?
Number objects are still objects. So their value is a reference, and if a function alters a property of an object passed as an argument, that object will be affected outside the function.
function changer(obj) {
obj.foo = 'bar';
}
var num = new Number(123);
console.log(num.foo); // undefined
changer(num);
console.log(num.foo); // 'bar'
However, the value wrapped inside the number object is not stored as a property. It's stored as a [[NumberData]] internal slot. ECMAScript provides no way to alter that slot, so you can't change the number.
Your attempt of fnc+1 unwraps the number object to get its [[NumberData]], and adds 1 to that. But the result is just discarded, it's not stored back in the [[NumberData]] slot of fnc.
If you want to be able to achieve something analogous to changing the [[NumberData]], you can
function MyNumber(num) {
this.__number__ = +num;
}
MyNumber.prototype = Object.create(Number.prototype);
Object.getOwnPropertyNames(Number.prototype).forEach(function(prop) {
var desc = Object.getOwnPropertyDescriptor(Number.prototype, prop);
if(desc && desc.value && typeof desc.value == 'function') {
var native = desc.value;
desc.value = function() {
return native.apply(this.__number__, arguments);
};
Object.defineProperty(MyNumber.prototype, prop, desc);
}
});
var num = new MyNumber(123);
console.log(+num, num+'', num.toFixed(2)); // 123, "123", "123.00"
num.__number__ = 456;
console.log(+num, num+'', num.toFixed(2)); // 456, "456", "456.00"
I actually had a lot issues when I started getting into the object side of JavaScript myself. Best way I can explain is by these examples.
Objects link.
var obj = {a: 5};
var b = obj.a;
b = 2;
// obj.a: 2
// b: 2
This will link to the object value I believe. So if you change b it will also change obj.a.
HTML DOM object link with odd behavior
var x = document.getElementById("some_div_id");
x.innerHTML = "example"; // this works
var x = document.getElementById("some_div_id").innerHTML;
x = "example"; // this doesn't, it thinks that it's document.getElementById("some_div_id");
Took me time to figure what was wrong when I first did the second DOM method.
Variables are not linked but copied.
var a = 5;
var b = a;
b = 2;
// a: 5
// b: 2
As you can see, this doesn't link the value but creates a new one based from it.
Deep copying from objects trick.
function deepCopy(objValue) {
return JSON.parse(JSON.stringify(objValue));
}
var obj = {a: 5};
var b = deepCopy(obj.a);
b = 2;
// obj.a: 5
// b: 2
This was a trick given to me some time back when I had issues wanting a object value being stored in a variable and edited but without it being linked to the object value. After a while I found I never needed it after improving my coding skills.
Also last note. I read somewhere in clean JavaScript coding that you shouldn't need to use the new object method unless it's a Date() object or or simulated class, or you may run into typeof and value check issues with ===.
Can't be certain if this is error free but hope this helps explains better.
In Javascript, objects refer to an array, indicated by [] or an object {}. You can verify the type of the variable by using typeof. These are passed by reference.
typeof [2, 5, 3] //object
typeof { a: 10} // object
If you pass the object literal to a function and modify the value of the property 'a', it would result in the value being modified.

Why does var a = ...arguments fail, if console.log(...arguments) is OK?

Code A, this is OK and logs [ 1, 2, 3 ]
function fn() {
console.log(...arguments);
}
fn([1, 2, 3]);
Code B, this fails with SyntaxError: Unexpected token ...
Also, wrapping ...arguments in () won't help either.
function fn() {
var a = ...arguments;
}
fn([1, 2, 3]);
In both cases, I assume, we have a RHS lookup. Why is it OK to pass on ...arguments to console.log (or other function), but not to assign it to a variable?
PS. I know that this would never stand in real life code or there are other, better solutions to this. My question is purely theoretical/conceptual and limited to understanding why the different behavior occurs.
The two applications of the spread syntax are:
turn items of an iterable value into arguments of a function call
turn items of an iterable into elements of an Array
So this works:
function fn() {
var a = [...arguments];
}
It doesn't work as in CODE B... Invalid syntax
You can spread in fn params like
function fn(...params)
{
...
}
or Array and Object
var a = [1,2,3,4,5],
b = [6,...a];
var x = {a:1,b:1},
y = {c:1,...x}

Categories