all. I'm new to JS. Here I met a JS question showed below:
function print(n) {
setTimeout(() => {
console.log(n);
}, Math.floor(Math.random() * 1000));
}
for (var i = 0; i < 100; i++) {
print(i);
}
The requirement is:
Math.floor(Math.random() * 1000
.Here I get some solutions for this question, but there are some of these answers I don't understand, so I hope you guys can help me why this can work. I understand the answers for the first one, the second one and the last one, but I am not quite clear why the rest of the answer can work. Especially for the third one, if I remove the code return ()=>{}
, the code still works but it will report an error 100Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src <URL> <URL> 'self' 'unsafe-inline' https:".
.
//1.
function print1(n) {
setTimeout(() => {
console.log(n);
}, 1, Math.floor(Math.random() * 1000));
}
// 2.
function print2(n) {
setTimeout(() => {
console.log(i--);
}, Math.floor(Math.random() * 1000));
}
// 3.
function print3(n) {
setTimeout((() => {
console.log(n)
return () => { }
}).call(n, []), Math.floor(Math.random() * 1000));
}
for (var i = 0; i < 100; i++) {
print(i);
}
//4.
function print4(n) {
setTimeout(() => {
setTimeout(() => {
console.log(n);
}, 1000 * n);
}, Math.floor(Math.random() * 1000));
}
// 5.
function print5(n) {
setTimeout((() => {
console.log(n);
})(), Math.floor(Math.random() * 1000));
}
The third approach essentially calls a function as soon as the setTimeout
line runs, before the timeout callback runs. So when print(i);
is called, the number is logged immediately, before the next iteration of the loop starts.
Functionally, it's similar to this:
function print3(n) {
console.log(n);
setTimeout(<unimporant>);
}
It works because the function inside the timeout is invoked immediately with the .call
:
setTimeout((() => {
console.log(n)
return () => { }
}).call(n, []),
simplifies to
setTimeout((() => {
console.log(n)
return () => { }
})(),
which is basically just
console.log(n)
setTimeout((() => {
return () => { }
})(),
or, substituting the returned function from the IIFE:
console.log(n)
setTimeout(() => {},
The callback passed to setTimeout
doesn't do anything.
if I remove the code return ()=>{}, the code still works but it will report an error
It sounds like you returned a string instead of the function at the end, which will result in the interpreter trying to run the string. While it's possible to do such a thing in some environments, it's basically the same thing as eval
.
setTimeout('console.log("never do this");');
which is why the warning comes up.