Javascript settimeout () not working [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
I am a javascript learner
Hear is my javascript
I have a javascript function named get();
which i call it onload.
function get() {
for (var i = 1; i <= 5; i++) {
setTimeout(function() {
console.log('Value of i : ' + i);
}, 100);
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
</head>
<body onload="get();">
</body>
</html>
The expected output is
Value of i : 1
Value of i : 2
Value of i : 3
Value of i : 4
Value of i : 5
where as i am getting
Value of i : 6
Not able to figure out what is exactly is wrong .

The correct approach to to do this is :
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
</head>
<script>
function get() {
for (var i = 1; i <= 5; i++) {
setTimeout(function(x) {
console.log('Value of i : ' + x);
}(i), 100);
}
}
</script>
<body onload="get();">
</body>
</html>
Notice the (i) in :
setTimeout(function(x) {
console.log('Value of i : ' + x);
}(i), 100);
}
this is how you pass values to a settimeout function.

You can use let that has its own scope or you can create a closure there.
Using let
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
</head>
<script>
function get() {
for (let i = 1; i <= 5; i++) {
setTimeout(function() {
console.log('Value of i : ' + i);
}, 100);
}
}
</script>
<body onload="get();">
</body>
</html>
Closure snippet
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
</head>
<script>
function get() {
for (let i = 1; i <= 5; i++) {
setTimeout(((function(i) {
return function() {
console.log('Value of i : ' + i);
}
})(i)), 100);
}
}
</script>
<body onload="get();">
</body>
</html>

Related

Why does one counter work and the other doesn't? (Closures?)

I have two questions about this counter example.
Why doesn't addVersionOne work? Why is it returning the actual code instead of a number?
How does addVersionTwo work? Isn't counter being reset back to 0 every time the function is run?
const addVersionOne = function() {
let counter = 0;
return function() {
counter += 1;
return counter;
}
}
var addVersionTwo = (function () {
let counter = 0;
return function() {
counter += 1;
return counter;
}
})();
function writeVersionOne(){
document.getElementById("addVersionOne").innerHTML = addVersionOne();
}
function writeVersionTwo(){
document.getElementById("addVersionTwo").innerHTML = addVersionTwo();
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<button type="button" onclick="writeVersionOne()">addVersionOne</button>
<button type="button" onclick="writeVersionTwo()">addVersionTwo</button>
<p id="addVersionOne">0</p>
<p id="addVersionTwo">0</p>
<script src="main.js"></script>
</head>
<body>
</body>
</html>
When you execute this:
addVersionOne()
What is the result? Well, let's see what that function returns:
//...
return function() {
counter += 1;
return counter;
}
It returns a function. That function is never executed, it's just returned. The function itself is being set as the innerHTML for your target element.
But what does this return?:
addVersionTwo()
Notice how your second version wraps everything in parentheses and then adds another set of parentheses to invoke the returned function. So while the variable addVersionOne is a function which returns a function, the variable addVersionTwo is that returned function. And it returns a value:
//...
return counter;
Isn't counter being reset back to 0 every time the function is run?
Which "function" are you referring to? You have several. This function is being executed once when the page loads:
function () {
let counter = 0;
return function() {
counter += 1;
return counter;
}
}
It then returns a function which is stored in the addVersionTwo variable. That function is:
function() {
counter += 1;
return counter;
}
And no, that function does not reset counter to 0 each time it is executed.
Because the return value of the function addVersionOne is a function and it is obvious. But addVersionTwo function is actually the result of a function call which returns a function. So, addVersionTwo is actually the function below:
return function() {
counter += 1;
return counter;
}
you could define the function addVersionTwo as follows:
var counter = 0;
var addVersionTwo = function() {
counter += 1;
return counter;
};

slideshow with page numbers javascript

I have created slideshow. I want to add some description with page numbers.
I was trying to add function sliderText() to get result - "Image 1 of 7" etc.
I don't know what is wrong here. Can somebody give me some hints?
Thank you in advance,
Megi
var img_index = 0;
var imgs = [
"assets/1.jpg",
"assets/2.jpg",
"assets/3.jpg",
"assets/4.jpg",
"assets/5.jpg",
"assets/6.jpg",
"assets/7.jpg"
];
function findNextImage(isPrev) {
switch (true) {
case !!(isPrev && imgs[img_index + 1]):
img_index += 1
return imgs[img_index]
case !!imgs[img_index + 1]:
img_index += 1
return imgs[img_index]
default:
img_index = 0
return imgs[img_index]
}
sliderText()
}
function checkKey(event) {
if (event.keyCode == '39') {
document.getElementById("images").src = findNextImage();
} else if (event.keyCode == '37') {
document.getElementById("images").src = findNextImage(true);
}
}
document.onkeydown = checkKey;
function sliderText() {
var text = document.getElementsByClassName("slideshow_text");
var imageNumber = img_index + 1;
text.innerHTML = "image " + imageNumber + " of " + imgs.length;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
</head>
<h1 class="slideshow_text">Image 1 of 7</h1>
<img id="images" src="assets/1.jpg" />
<body>
</body>
<script src="test.js"></script>
</html>
Some modifications to improve code quality
I removed findNextImage which was not a pure function and introduced findNextImageIndex instead: findNextImageIndex neither accesses nor modifies any external variables and is thus easier to read. sliderText takes imgIndex as an argument so that you can easily see what parameters it needs to set the text.
Further suggestions
Consider moving the pre-set values Image 1 of 7 and "assets/1.jpg" from HTML to JavaScript as well. Initialize the slider with "assets/1.jpg" taken from the array and call sliderText(state.imgIndex); once initially.
Please notice that I moved the slide show HTML inside the <body> to make it valid HTML.
Modified code
var state = {
imgIndex: 0
};
var imgs = [
"assets/1.jpg",
"assets/2.jpg",
"assets/3.jpg",
"assets/4.jpg",
"assets/5.jpg",
"assets/6.jpg",
"assets/7.jpg"
];
function findNextImageIndex(imgIndex, isPrev) {
if(isPrev) {
if(imgIndex <= 0) {
return imgs.length - 1;
} else {
return imgIndex - 1;
}
} else {
if(imgIndex >= imgs.length - 1) {
return 0;
} else {
return imgIndex + 1;
}
}
}
function sliderText(imgIndex) {
var text = document.getElementsByClassName("slideshow_text")[0];
var imageNumber = imgIndex + 1;
text.innerHTML = "image " + imageNumber + " of " + imgs.length;
}
function goToNextImage(isPrev) {
state.imgIndex = findNextImageIndex(state.imgIndex, isPrev);
document.getElementById("images").src = imgs[state.imgIndex];
sliderText(state.imgIndex);
}
function checkKey(event) {
switch(event.keyCode) {
case 37: goToNextImage(true); break;
case 39: goToNextImage(false); break;
}
}
document.onkeydown = checkKey;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
</head>
<body>
<h1 class="slideshow_text">Image 1 of 7</h1>
<img id="images" src="assets/1.jpg" />
<script src="test.js"></script>
</body>
</html>

Javascript - novice script not working

could someone explain why this script isn't working? I tried to figure it out for long time, but I didn't manage to do it.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<script>
function Xyz() {
var x = 0;
}
function Switch() {
if (x == 0) {
document.body.style.backgroundColor = "black";
x = 1;
}
else {
document.body.style.backgroundColor = "white";
x = 0;
}
}
</script>
</head>
<body>
<button type="button" onclick="Switch()">Click me</button>
</body>
</html>
if(x==0)
Since x doesn't exist, it throws a ReferenceError here and aborts the rest of the function.
You need to declare x first.
This:
function Xyz()
{
var x=0;
}
Creates a variable x that is local to the function and
Is never called anyway
You need to define variable x. I used hoisting in this example.
<!DOCTYPE html>
<html>
<head>
<script>
function Xyz()
{
var x=0;
}
function Switch()
{
if(x==0)
{
document.body.style.backgroundColor="black";
x=1;
}
else
{
document.body.style.backgroundColor="white";
x=0;
}
}
var x;
</script>
</head>
<body>
<button type="button"onclick="Switch()">Click me</button>
</body>
</html>
Issue is You need to declare a variable before using it.
function Switch()
{
if(x==0) // this x is not defined.
{
document.body.style.backgroundColor="black";
x=1;
}
else
{
document.body.style.backgroundColor="white";
x=0;
}
}
Since you need to use the same variable to update it with each click , define it outside function.
<!DOCTYPE html>
<html>
<head>
<script>
var x = 0;
function Xyz()
{
var x=0;
}
function Switch()
{
if(x==0)
{
document.body.style.backgroundColor="black";
x=1;
}
else
{
document.body.style.backgroundColor="white";
x=0;
}
}
</script>
</head>
<body>
<button type="button"onclick="Switch()">Click me</button>
</body>
</html>

Changing color code doesn't work

function color(){
var color = "#"
for(var i = 0; i<6; i++){
color += Math.floor((Math.random()*16)).toString(16);
};
document.getElementsByTagName('body')[0].style.backgroundColor = color;
}
function change(){
setInterval(color(), 1000);
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<button id='button' onmouseover="change();" style='width:50px; height:50px; margin-left:auto;'>click</button>
<script type="text/javascript" src='js.js'></script>
</body>
</html>
I tried to make the auto changing background coding.
I want to change the background color every 1 second.
but it just change color once when i put my mouse on.
what is the problem?
You're calling the function, not referencing it in the setInterval call.
Change it to
setInterval(color, 1000);
FIDDLE
When you add the parentheses to a function, it's called, and the returned result, which is always undefined unless something else is defined in the called function, will be returned.
What you're doing is the same as
var fn = color(); // returns undefined
setInterval(fn, 1000); // undefined, 1000
Here's a working snippet.
What I changed was
onmousehover was replaced with oneclick() (since it says click on the button)
In the setInterval function call, color doesn't need the brackets
function color(){
var color = "#"
for(var i = 0; i<6; i++){
color += Math.floor((Math.random()*16)).toString(16);
};
document.getElementsByTagName('body')[0].style.backgroundColor = color;
}
function change(){
setInterval(color, 1000);
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<button id='button' onclick="change();" style='width:50px; height:50px; margin-left:auto;'>click</button>
<script type="text/javascript" src='js.js'></script>
</body>
</html>
</html>
Here is a working example
<body>
<button id='button' onmouseover="change()" style='width:50px; height:50px; margin-left:auto;'>click</button>
</body>
<script>
function color() {
var color = "#"
for (var i = 0; i < 6; i++) {
color += Math.floor((Math.random() * 16)).toString(16);
};
document.getElementsByTagName('body')[0].style.backgroundColor = color;
}
function change() {
setInterval(color(), 1000);
}
</script>
Fiddle: https://jsfiddle.net/9cxw9jL0/
I have changes some code and you can find in plunker.
<https://plnkr.co/edit/sKpJQqRohICD63AQjgTx?p=preview>
Here is the solution for your problem
function colorchanger(){
setInterval(function(){
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
document.body.style.backgroundColor = color;
},300);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
<button onclick="colorchanger();" >Change Color</button>
</body>
</html>

Javascript SetTimeout chaining

This may be a simple problem but I can't seem to embed a variable parameter in a function for future execution. "alert" is the function I'd like to delay execution, with the parameter 0, 1, 2 etc
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script language="JavaScript">
var init = function init() {
for (var i = 0, max = 3; i < max; i++) {
var then;
then = (function(jj) {
return jj;
}(i));
var pp = function(jj) {
return alert(then);
};
setTimeout(function() {
pp();
}, then * 1000);
}
};
</script>
</head>
<body onload="init();">
<button onclick="init();"></button>
</body>
</html>
You didn't really ask a question so I'll assume any implementation that produces the results you were expecting is what you want.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script language="JavaScript">
function createfunc(i) {
return function() { alert(i); };
}
var init = function init() {
for (var i = 0, max = 3; i < max; i++) {
var func = createfunc(i);
setTimeout(func, i * 1000);
}
};
</script>
</head>
<body onload="init();">
<button onclick="init();"></button>
</body>
</html>
This will alert a number, then wait a second and alert another number. Until 3 is reached:
var init = function() {
var counter = 0, //Start
max = 3 //End
var count = function() {
alert(counter) //Alert
if ( counter < max ) { //If we havent reached 3 then queue this function to be called again
window.setTimeout(function() {
count()
}, 1000)
}
counter++
}
count() //Start the counter
}
Here is a fiddle: http://jsfiddle.net/EXwH2/1/
You enclosed the first function in a closure but not the second, so you essentially set your pp var to the last iteration before setTimeout is called for the first time. What's your intent with the then variable? If you want to stagger the calls, each with their own value, you might want to put the call to setTimeout itself within its own closure:
var init = function init() {
for (var i = 0, max = 3; i < max; i++) {
(function (jj) {
setTimeout(function() {
alert(jj);
}, jj * 1000);
})(i);
}
};

Categories