I have seperated your functions into incorrect and correct one.
The incorrect version is what you're asking. The correct version is what you've already figured out but don't know why it work.
In the incorrect version, the value of i will always be updated to the most recent value because i belongs to the createButtons function and is shared with all onclick handler, and it is changing with the loop.
In the correct version, the value of i is given to the IIFE as num, and num belongs to the IIFE and not to createButtons.
Because of that, num is fixed because a new num is created for every loop thus is not shared with the other onclick handler.
Why? It is how closure works in JavaScript.
Read this for deeper understanding on JavaScript closure.
function createButtons_incorrect() {
for (var i = 1; i <= 5; i++) {
var body = document.getElementsByTagName("BODY")[0];
var button = document.createElement("BUTTON");
button.innerHTML = 'Bad ' + i;
button.onclick = function() {
alert('This is button ' + i);
}
body.appendChild(button);
}
}
function createButtons_correct() {
for (var i = 1; i <= 5; i++) {
var body = document.getElementsByTagName("BODY")[0];
var button = document.createElement("BUTTON");
button.innerHTML = 'Good ' + i;
(function(num){
button.onclick = function() {
alert('This is button ' + num);
}
})(i);
body.appendChild(button);
}
}
createButtons_incorrect();
document.body.appendChild(document.createElement('br'));
createButtons_correct();