I'm Getting warning don't make functions within a loop on my code i'm using jslint my questions are
/*global prompt,alert,console,rgb*/
/*jslint plusplus: true */
/*jshint loopfunc: true */
var colors = [
'rgb(255, 0, 0)',
'rgb(255, 255, 0)',
'rgb(255, 255, 255)',
'rgb(0, 255, 255)',
'rgb(0, 255, 0)',
'rgb(0, 0, 255)'
];
var pickedColor = colors[2];
var square = document.querySelectorAll(".square");
var i;
var colorMatch = document.querySelector(".pickedColor");
for (i = 0; i < square.length; i++) {
//add different color to square
square[i].style.background = colors[i];
//add eventlistner to square
square[i].addEventListener('click', function () {
'use strict';
var selectedColor = (this.style.background);
if (selectedColor === pickedColor) {
console.log("True");
} else {
console.log('False');
}
});
}
colorMatch.textContent = pickedColor;
body{
background: rgb(52, 73, 94);
}
h1{
color: white;
}
.container{
margin: 0 auto;
max-width: 600px;
}
.square{
width: 30%;
margin: 1.66%;
background-color: purple;
padding-bottom: 30%;
float: left;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Color Game</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>The Great <spam class="pickedColor"
>RGB</spam> Color Game</h1>
<div class="container">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
<script src="script.js"></script>
</body>
</html>
In the meantime, thank you so much for your attention and participation.
In that specific case, you could ignore the warning, because your functions don't use any variables they close over (like i
) that change in the course of the loop.
But since they don't, there's no reason to create several copies of the function when just one will do:
function squareClick() {
'use strict';
var selectedColor = (this.style.background);
if (selectedColor === pickedColor) {
console.log("True");
} else {
console.log('False');
}
}
for (i = 0; i < square.length; i++) {
//add different color to square
square[i].style.background = colors[i];
//add eventlistner to square
square[i].addEventListener('click', squareClick);
}
Where it would be a problem:
Suppose you did this and there were 8 squares:
for (i = 0; i < square.length; i++) {
square[i].addEventListener('click', function() {
alert(i); // <=== Using i
});
}
When you clicked those squares, you'd see the value 8, no matter which square you clicked, because those functions have a live reference to the i
variable, not a copy of the variable as of when they were created.
That's part of why jsLint warns you about this: Either you need to be careful (because you're using i
), or it's pointless to create functions in the loop (because you aren't using anything that varies).
Final note: In ES2015, you could safely do this:
for (let n = 0; n < square.length; n++) {
square[n].addEventListener('click', function() {
alert(n); // <=== Using n
});
}
...and you'd see 0, 1, 2, ... 7 depending on what square you clicked. This is because the ES2015+ semantics of the let
declarations within for
loops is specifically designed to ensure that each loop iteration gets its own copy of n
. This is very different from the seemingly-near-identical version using var
.
Example with var
; they all show 8:
var square = document.querySelectorAll(".square");
for (var i = 0; i < square.length; i++) {
square[i].addEventListener('click', function() {
alert(i); // <=== Using i
});
}
<div class="square">zero</div>
<div class="square">one</div>
<div class="square">two</div>
<div class="square">three</div>
<div class="square">four</div>
<div class="square">five</div>
<div class="square">six</div>
<div class="square">seven</div>
Example with let
(on ES2015+ compliant browsers); they show 0...7:
var square = document.querySelectorAll(".square");
for (let n = 0; n < square.length; n++) {
square[n].addEventListener('click', function() {
alert(n); // <=== Using n
});
}
<div class="square">zero</div>
<div class="square">one</div>
<div class="square">two</div>
<div class="square">three</div>
<div class="square">four</div>
<div class="square">five</div>
<div class="square">six</div>
<div class="square">seven</div>
Note that the let
has to be within the for
for this treatment to kick in. That is,
let n;
for (n = 0; n < square.length; ++n)
is very different from
for (let n = 0; n < square.length; ++n)
The former would act like var
in terms of functions created within the loop. The latter does not.