I want to change the content and add a class to the element clicked with javascript.
If i try to assign a class after specifying the character string stored in the array by passing the number specified in the loop, it will be undefined.

The problem i am having

The processing of classList.add (cls [i]) inserts undefined.

Corresponding source code
        document.addEventListener ('DOMContentLoaded', function () {
            var btns = document.querySelectorAll ('.btn');
            let cls = ["btn01", "btn02", "btn03"]
            for (var i = 0;i<btns.length;i ++) {
                btns [i] .addEventListener ('click', function () {
                    this.innerHTML = "It's changed";
                    this.classList.add (cls [i])
                }, false);
        }, false);
  • Answer # 1


    Since i is not block-scoped, it cannot hold a value for each loop and is incremented after the loop ends, so it goes beyond the scope of the array and is undefined.

    Common mistakes: Creating closures inside a loop | Closures --JavaScript | MDN

  • Answer # 2

    i is referenced "after clicking".
    The value of i is "3" after the for is removed.
    Since 3 is an index that cls does not have, it will be undefined.
    Therefore, it is better to reorganize to get the number of the class in which the event occurred.

  • Answer # 3

    I've done the same before,

    btns [i] .addEventListener ('click', function () {
         this.innerHTML = "It's changed";
         this.classList.add (cls [i])
     }, false);

    That's because i has been used in.
    Specifically, this is the part of this.classList.add (cls [i]).

    If you think about it normally, when each button is pressed, it seems that 0 to 2 are in order in the above i, but it is different.
    btns [i] .addEventListener ('click', function () {
    }, false);

    The program inIt is executed when the click event occurs, and the contents of i at that timing are applied.

    In other words, once this program is executed, the for statement turns, and when i is added and i becomes 3, the loop is exited.
    When a click event occurs after that
    this.classList.add (cls [3])
    It means that it will be processed like this.

  • Answer # 4


    If you want to make the minimum correction, you can use the loop counter.iTovarnotlet letIf you declare and initialize with, it will be as intended.

    --for (var i = 0;i<btns.length;i ++) {
    + for (let i = 0;i<btns.length;i ++) {

    Sample for operation check:https://codepen.io/jun68ykt/pen/oNxEaOv?editors=0010

  • Answer # 5

    const cls = ["btn01", "btn02", "btn03"];
    document.querySelectorAll ('.btn'). forEach ((x, y) =>{
      x.addEventListener ('click', () =>{
        x.textContent = "It has changed";
        x.classList.add (cls [y]);

Related articles