Счетчик кликов для разных кнопок с помощью замыканий JS

Задание звучит так: Даны кнопки. Привяжите к каждой кнопке событие по клику, которое будет считать количество нажатий по кнопке и выводить его в текст кнопки. Количество нажатий для каждой кнопки должно хранится в замыкании.

У меня получилось создать только счетчик, который считает клики по всем кнопкам, но не по отдельности (если я кликнул на кнопку1 3 раза, то кликнув на кнопку2 вместо 1 я получу 4 а после клика на кнопку3 я получу 5). Если я пытаюсь отдельно для каждой кнопки описать счетчик, то получаю ошибку res is not a function:

   btn1.addEventListener('click', function(){
        function func (){
            let k = 0;
            function count(){
               return k++
            }
            return count()
        }
        let res = func();
        btn1.innerText = res()
    })

Можно ли как-то разделить счетчик, чтобы он считал клики для каждой кнопки отдельно начиная с 0?

Вот мой код, в котором счетчик работает для всех кнопок вместе:

    btn1 = document.getElementById('1')
    btn2 = document.getElementById('2')
    btn3 = document.getElementById('3')
    function func() {
        let k = 0;
        return function count() {
            return k++
        }
    }

    let res = func ()
    btn1.onclick = () => {
        btn1.innerText = res()
    }
    btn2.onclick = () => {
        btn2.innerText = res()
    }
    btn3.onclick = () => {
        btn3.innerText = res()
    }

Ответы (3 шт):

Автор решения: Проста Miha

Попробуйте как-то вот так

const clickBtns = document.querySelectorAll('.clicker');

for (let elem of clickBtns) {
  elem.addEventListener('click', (e) => {
    if (!isNaN(parseInt(e.target.innerHTML))) {
      e.target.innerHTML = parseInt(e.target.innerHTML) + 1;
    } else {
      e.target.innerHTML = 1;
    }
  })
}
<button class='clicker'>Кнопка</button>

<button class='clicker'>Кнопка</button>

<button class='clicker'>Кнопка</button>

→ Ссылка
Автор решения: Neverm1ndo

Вот типичный счетчик с использованием замыканий. Ваша ошибка была только в том, что вы не создавали отдельный счетчик для каждой кнопки, а использовали один для всех - res.

const buttons = document.querySelectorAll('button'); // получаем NodeList с кнопками

/**
* Функция счетчика
*/
function count() {
  let counter = 0;
  return function() {
    return counter+=1;
  };
}

for (let button of buttons) {
  const counter = count(); // создаем отдельный инстанс функции счетчика для каждой кнопки
  button.addEventListener('click', function() {
    this.textContent = counter(); // прибавляем +1 к счетчику внутри counter
  });
}
<button>0</button>
<button>0</button>
<button>0</button>

→ Ссылка
Автор решения: Qwertiy

Вряд ли ждут такого ответа, но формально это тоже замыкание:

for (let btn of document.querySelectorAll("button")) {
  let clicks = 0
  
  btn.addEventListener('click', e => {
    btn.textContent = ++clicks
  })
}
button { min-width: 7ch }
<button>0</button>
<button>0</button>
<button>0</button>
<button>0</button>
<button>0</button>

А ожидают увидеть скорее всего что-то такое:

function makeClickHandler() {
  var clicks = 0
  return e => e.target.textContent = ++clicks
}

for (let btn of document.querySelectorAll("button")) {
  btn.addEventListener('click', makeClickHandler())
}
button { min-width: 7ch }
<button>0</button>
<button>0</button>
<button>0</button>
<button>0</button>
<button>0</button>

Есть ещё один вариант, который тоже использует замыкание, но почти наверняка его забракуют как и первый:

function main() {
  var clicks = new Map()
  
  document.addEventListener('click', e => {
    var btn = e.target.closest('button')
    
    if (btn) {
      var count = (clicks.get(btn) ?? 0) + 1
      clicks.set(btn, count)
      btn.textContent = count
    }
  })
}

main()
button { min-width: 7ch }
<button>0</button>
<button>0</button>
<button>0</button>
<button>0</button>
<button>0</button>

Ну и в качестве бонуса, как бы я сделал такой счётчик без требования на использование замыкания:

document.addEventListener('click', e => {
  var btn = e.target.closest('button')
  if (btn) ++btn.textContent
})
button { min-width: 7ch }
<button>0</button>
<button>0</button>
<button>0</button>
<button>0</button>
<button>0</button>

→ Ссылка