-1

How to create a copy of a variable without declaring a new variable?

I want btn1 to behave like btn3.

i = 1;

btn1.addEventListener('click', function() {
  fkt(i); // do not reference i, but instead copy current value of i

  //fkt(i.copy()); //doesn't work
}, false);

let currentValue = i;
btn3.addEventListener('click', function() {
  fkt(currentValue);
}, false);

btn2.addEventListener('click', function() {
  i++;
}, false);

function fkt(number) {
  console.log(number);
}
<button id='btn1'>print i</button>
<button id='btn2'>increase i</button>

<button id='btn3'>print correct</button>
user1
  • 404
  • 1
  • 5
  • 18
  • 1
    Why do you want to create a copy of an immutable value? – Carcigenicate Jan 04 '20 at 23:02
  • @Carcigenicate why is `i` immutable? `btn2` increases `i` – user1 Jan 04 '20 at 23:02
  • When you say `let currentValue = i;`, that's a copy of a value `i` into a different variable `currentValue`. The two are not aliases. If you want `btn1` to behave like `btn3`, call `fkt(currentValue)`, which is never incremented just like `btn3`'s callback does. Perhaps this is an [xy problem](https://meta.stackexchange.com/a/233676/399876)? – ggorlen Jan 04 '20 at 23:04
  • So you want btn3 to always output 1 regardless of what happens to i? – Nick Jan 04 '20 at 23:05
  • @Nick yes that is correct. and `btn1` also should always print `1` – user1 Jan 04 '20 at 23:06
  • 2
    When you rephrase “create a copy of a variable” as what you’re actually doing – storing the current *value* of a variable somewhere else – it becomes clearer that you need *somewhere* to store it. There are lots of places that aren’t technically variables that work for this (e.g. `function(i) { … }.bind(null, i)`), but these are similar in many respects. Maybe the better question is why you don’t want to use a variable? – Ry- Jan 04 '20 at 23:07
  • @ggorlen at the moment I add the event listener to `btn1` `i=1` holds. Therefore I want `btn1` to always print `1` – user1 Jan 04 '20 at 23:09
  • 1
    Replace `fkt(i)` with `btn3.click()` - Bingo, it's now definitely going to behave as btn3 – Shiny Jan 04 '20 at 23:12
  • @ggorlen well... imagine there is an other button that overrides the the event listener of `btn1` to print the current value at this moment – user1 Jan 04 '20 at 23:13
  • @Light `btn3` doesn't actually exist. It's just here to show what I mean – user1 Jan 04 '20 at 23:13
  • So, should both `btn1` and `btn3` simply print `1` (the initial value of `i` at the time the two handlers are created)? – VLAZ Jan 04 '20 at 23:15
  • @Ry- I guess by now it is clear why I want to use a variable. I'm not sure if I understand you right. I'm not quite familiar with anonymous functions, ... – user1 Jan 04 '20 at 23:18
  • In javascript whatever you put inside event-callback-function will executed on event time (after click). Even if you put an syntax error you will not see any error before clicking on btn. So you need to do something outside the event-callback-function – Ali Jan 04 '20 at 23:18
  • @Ben: Are you saying you’re going to use a variable after all, or is that a typo for “why I don’t want to”? (Because it’s not really clear why you didn’t want to…) – Ry- Jan 04 '20 at 23:27
  • @Ry- I need the variable `i` but want to get rid of the variable `currentValue` – user1 Jan 04 '20 at 23:30
  • @Ben: Why do you want to get rid of the variable `currentValue`? – Ry- Jan 04 '20 at 23:32
  • @Ry- I want to increase performance and **get a cleaner code**. I see no reason to declare the variable `currentValue`, all I want is to refer to the current value of `i` (maybe also my other comments under @Nick's answer help you) – user1 Jan 04 '20 at 23:34
  • @Ben: Well, it’s definitely not going to make a difference in performance, and it’s pretty clean as-is. If there’s something you’re unhappy with in the broader code (this doesn’t have enough context to say anything beyond “just keep the variable”), try asking about it on [CodeReview.SE]. – Ry- Jan 04 '20 at 23:41

2 Answers2

1

You could use a closure to create btn3 event handler. That will lock in the value of i at the time the event handler is created, i.e. 1.

i = 1;

btn1.addEventListener('click', function() {
  fkt(i); // do not reference i, but instead copy current value of i

  //fkt(i.copy()); //doesn't work
}, false);

(function(currentValue) {
  btn3.addEventListener('click', function() {
    fkt(currentValue);
  }, false)
})(i);

btn2.addEventListener('click', function() {
  i++;
}, false);

function fkt(number) {
  console.log(number);
}
<button id='btn1'>print i</button>
<button id='btn2'>increase i</button>

<button id='btn3'>print correct</button>
Nick
  • 138,499
  • 22
  • 57
  • 95
  • This behaves like my code? – user1 Jan 04 '20 at 23:18
  • @Ben yes - button 3's event handler is created with the value of `i` at the time of its creation. Try it... – Nick Jan 04 '20 at 23:20
  • oh, I see the difference. But does this save any space? It seems more complex – user1 Jan 04 '20 at 23:22
  • What do you mean by space? – Nick Jan 04 '20 at 23:23
  • storage on the disc – user1 Jan 04 '20 at 23:23
  • Well, you can shorten the code if that's what you're concerned about (e.g. by using arrow functions or shorter variable names). But if that's all you're concerned about then your current code is fine as is. Why is it an issue? – Nick Jan 04 '20 at 23:26
  • I want to increase performance and **get a cleaner code**. I see no reason to declare the variable `currentValue`, all I want is to refer to the current value of `i` – user1 Jan 04 '20 at 23:29
  • Well, this will do that, it will effectively create the event handler for btn3 as `fkt(1)` – Nick Jan 04 '20 at 23:30
1

You can have a function that creates the callbacks for the event handlers. You can use this to capture the current value of i in a closure and thus you'd get the value at the time of creating the callback, it will not change with i at a later point. As an additional benefit, you can ensure both event handlers work exactly the same - you don't have repeated code that might get out of sync:

i = 1;

const makeCallback = value => () => fkt(value);

btn1.addEventListener('click', makeCallback(i), false);
btn3.addEventListener('click', makeCallback(i), false);

btn2.addEventListener('click', function() {
  i++;
}, false);

function fkt(number) {
  console.log(number);
}
<button id='btn1'>print i</button>
<button id='btn2'>increase i</button>

<button id='btn3'>print correct</button>
VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • `btn3` doesn't exist in my real code. So I only got `btn1`. With this information (and the comments under @Nick's answer) do you think, that his answer is preferable? – user1 Jan 04 '20 at 23:33
  • I don't think it matters that much. Both of these do the same thing using the same fundamental concept to enable it - it's just trapping the value of a variable in a closure. I am biased, obviously, but I prefer my version because I personally find it more readable. I don't think this makes Nick's version wrong, though - if I saw something similar in a code review at work, I'd probably accept it without an issue. – VLAZ Jan 04 '20 at 23:37