4

I have a function that has named arguments.

I am trying to call the same function from different events without overwriting the values of the others previously assigned.

I have tried store the values of the previously clicked buttons in variables but that doesn't work.

Is there a way to call the functions and assign a single argument at a time without overwriting the others?

function mainFun({
  val1,
  val2,
  val3
}) {
  var value1 = val1,
    value2 = val2,
    value3 = val3;
  // console.log(value1, value2, value3);
  console.log(val1, val2, val3);
}
<button onclick="mainFun({val1 : 'Caller 1'})">First Event</button>
<button onclick="mainFun({val2 : 'Caller 2'})">Second Event</button>
<button onclick="mainFun({val3 : 'Caller 3'})">Third Event</button>

Trying to achieve:

On First Event > Caller 1 undefined undefined

On Second Event > Caller 1 Caller 2 undefined

On Third Event > Caller 1 Caller 2 Caller 3

Thanks in advance!

O.O
  • 1,389
  • 14
  • 29
  • 1
    Your function implementation would have to be significantly different; you'd have to persist those values somewhere. Parameters are effectively local variables to a function, so they're newly created on each function call. – Pointy Apr 10 '19 at 12:45
  • Is there a similar question on how to `persist` these values? @Pointy – O.O Apr 10 '19 at 12:48

3 Answers3

4

You could store the values as property of the function.

function mainFun({ val1 = mainFun.val1, val2 = mainFun.val2, val3 = mainFun.val3 }) {
    mainFun.val1 = val1;
    mainFun.val2 = val2;
    mainFun.val3 = val3;

    console.log(val1, val2, val3);
}
<button onclick="mainFun({ val1: 'Caller 1' })">First Event</button>
<button onclick="mainFun({ val2: 'Caller 2' })">Second Event</button>
<button onclick="mainFun({ val3: 'Caller 3' })">Third Event</button>

If you do not like to store the values as properties of the function, you could use a closure and return a function for the same group of use cases.

function mainFun(defaults = {}) {
    return function({ val1 = defaults.val1, val2 = defaults.val2, val3 = defaults.val3 }) {
        defaults.val1 = val1;
        defaults.val2 = val2;
        defaults.val3 = val3;

        console.log(val1, val2, val3);
    };
}

var work = mainFun();
<button onclick="work({ val1: 'Caller 1' })">First Event</button>
<button onclick="work({ val2: 'Caller 2' })">Second Event</button>
<button onclick="work({ val3: 'Caller 3' })">Third Event</button>
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 1
    Not my question, just out of curiosity: how/why does this work? Doesn't every onclick create a new instance of mainFunc? (edit: this question referred to your answer before the edit) – Frank Apr 10 '19 at 12:52
  • 1
    @Frank, no it's always the same function. the values are stored in the properties of the function, because [functions are first class objects](https://stackoverflow.com/questions/705173/what-is-meant-by-first-class-object). – Nina Scholz Apr 10 '19 at 12:55
  • Exactly what I needed, was trying to avoid using variables inside or outside the scope of the function. – O.O Apr 10 '19 at 12:56
1

value1, value2and value3 variables are local to your mainFun function. They're being garbage collected after each mainFun execution is done.

To achieve what you want to achieve, you'll need to store the previous parameters somewhere.

There are many possibilities :

  • One of them is global variables :

let value1, value2, value3;

function mainFun({
  val1,
  val2,
  val3
}) {
    value1 = val1 || value1;
    value2 = val2 || value2;
    value3 = val3 || value3;
   console.log(value1, value2, value3);
  //console.log(val1, val2, val3);
}
<button onclick="mainFun({val1 : 'Caller 1'})">First Event</button>
<button onclick="mainFun({val2 : 'Caller 2'})">Second Event</button>
<button onclick="mainFun({val3 : 'Caller 3'})">Third Event</button>
  • Another solution would be to store them as the functions properties (as Nina Scholz suggested)
Guillaume Georges
  • 3,878
  • 3
  • 14
  • 32
1

Please correct me if I'm misunderstanding your question. But if you want to store te values, you'll have to declare them outside of your function. Currently your values are only alive within your function. When the function is called they will be re-created and after the function finishes they will be deleted again.

You could try to declare your values outside of your function and prevent overriding like this:

var value1, value2, value3;
function mainFun({
  val1,
  val2,
  val3
}) {
   value1 = value1 || val1,
    value2 = value2 || val2,
    value3 = value3 || val3;
  console.log(value1, value2, value3);
}

what the value1 || val1 basically does is say 'hey, if value1 already has a value, use that one. If not, use val1. Acts the same as value1 = value1 !== undefined ? val1 : value1 or easier:

if (value1 === undefined) {
   value1 = val1;
} else { // obviously not needed
   value1 = value1;
}