Evan Simanovskis
Evan Simanovskis

Reputation: 102

Functions in loop using same variable

I'm trying to make a calculator app with JavaScript and I want to have a function that gets called whenever a button is pressed. Here is my latest attempt.

const buttonIDs = [
  '0',
  '1',
  '2',
  '3',
  '4',
  '5',
  '6',
  '7',
  '8',
  '9',
  '*',
  '/',
  '+',
  '-',
  '.',
  '=']

for (var i = 0; i < buttonIDs.length; i++) {
  id = buttonIDs[i]
  button = document.getElementById(id)

  button.addEventListener('click', () => { buttonClicked(id) } )
}

function buttonClicked(id) {
  alert(id)
}
* {
  font-size: 100%;
  font-family: "Segoe UI",Arial,sans-serif;
  background-color: gray;
  outline: 0;
}

.wrapper {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 10px;
}

.box {
  padding: 20px;
  background-color: #aaa;
  border-radius: 3px;
}

.box.result {
  grid-column:1/5;
}

button {
  border: 0px;
  cursor: pointer;
}
<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>Vanilla JavaScript Calculator</title>

</head>

<body>
  <div class="wrapper">
    <input type="text" name="result" id="result" value="" readonly class="box result"></input>
    <button id="7" type="button" class="box 7">7</button>
    <button id="8" type="button" class="box 8">8</button>
    <button id="9" type="button" class="box 9">9</button>
    <button id="/" type="button" class="box divide">/</button>
    <button id="4" type="button" class="box 4">4</button>
    <button id="5" type="button" class="box 5">5</button>
    <button id="6" type="button" class="box 6">6</button>
    <button id="*" type="button" class="box multiply">*</button>
    <button id="1" type="button" class="box 1">1</button>
    <button id="2" type="button" class="box 2">2</button>
    <button id="3" type="button" class="box 3">3</button>
    <button id="-" type="button" class="box subtract">-</button>
    <button id="0" type="button" class="box 0">0</button>
    <button id="." type="button" class="box decimal">.</button>
    <button id="=" type="button" class="box equals">=</button>
    <button id="+" type="button" class="box add">+</button>
  </div>
</body>
</html>

Whenever a button is pressed, I get a popup that says "=". I think this is because when it loops through the elements in the array, the equals sign is the last thing that gets declared so it's what gets remembered. In Python, I could use keyword arguments, lambda id=id: buttonClicked(id). Is there something similar in JavaScript? Thanks in advance.

Upvotes: 1

Views: 44

Answers (2)

blurfus
blurfus

Reputation: 14031

I went and modified your JS functions like this. It seems to work...

See working demo below

for (var i = 0; i < buttonIDs.length; i++) {
  id = buttonIDs[i];
  var button = document.getElementById(id);
  button.addEventListener('click', buttonClicked);
}

function buttonClicked() {
  console.log(this.innerHTML);
}

const buttonIDs = [
  '0',
  '1',
  '2',
  '3',
  '4',
  '5',
  '6',
  '7',
  '8',
  '9',
  '*',
  '/',
  '+',
  '-',
  '.',
  '='
];

for (var i = 0; i < buttonIDs.length; i++) {
  id = buttonIDs[i];
  var button = document.getElementById(id);
  button.addEventListener('click', buttonClicked);
}

function buttonClicked() {
  console.log(this.innerHTML);
}
* {
  font-size: 100%;
  font-family: "Segoe UI", Arial, sans-serif;
  background-color: gray;
  outline: 0;
}

.wrapper {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 10px;
}

.box {
  padding: 20px;
  background-color: #aaa;
  border-radius: 3px;
}

.box.result {
  grid-column: 1/5;
}

button {
  border: 0px;
  cursor: pointer;
}
<!doctype html>

<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>Vanilla JavaScript Calculator</title>

</head>

<body>
  <div class="wrapper">
    <input type="text" name="result" id="result" value="" readonly class="box result"></input>
    <button id="7" type="button" class="box 7">7</button>
    <button id="8" type="button" class="box 8">8</button>
    <button id="9" type="button" class="box 9">9</button>
    <button id="/" type="button" class="box divide">/</button>
    <button id="4" type="button" class="box 4">4</button>
    <button id="5" type="button" class="box 5">5</button>
    <button id="6" type="button" class="box 6">6</button>
    <button id="*" type="button" class="box multiply">*</button>
    <button id="1" type="button" class="box 1">1</button>
    <button id="2" type="button" class="box 2">2</button>
    <button id="3" type="button" class="box 3">3</button>
    <button id="-" type="button" class="box subtract">-</button>
    <button id="0" type="button" class="box 0">0</button>
    <button id="." type="button" class="box decimal">.</button>
    <button id="=" type="button" class="box equals">=</button>
    <button id="+" type="button" class="box add">+</button>
  </div>
</body>

</html>

Upvotes: 2

Emiliano Barboza
Emiliano Barboza

Reputation: 485

Maybe you can use the event (e) and use the id, since the number is the id

button.addEventListener('click', function (e) { alert(e.target.id)} )

Upvotes: 1

Related Questions