This question already has answers here:
What does var mean in Javascript? [closed]
(2 answers)
Closed 2 years ago.
<script>
var start;
function shapeAppear() {
document.getElementById("shapes").style.display = "block";
var start = new Date().getTime();
}
function delay() {
setTimeout(shapeAppear,Math.random() *2000);
}
delay();
document.getElementById("shapes").onclick = function() {
document.getElementById("shapes").style.display = "none";
var position = Math.floor(Math.random() * 500);
document.getElementById("shapes").style.left = position + "px";
document.getElementById("shapes").style.right = position + "px";
document.getElementById("shapes").style.top = position + "px";
document.getElementById("shapes").style.bottom = position + "px";
var end = new Date().getTime();
var time = end - start;
time /= 1000;
document.getElementById("time").innerHTML = time + "s";
delay();
}
</script>
Here in this code i want the date() function to return a specific integer value.
Because when we subtract the two Date() functions we must get the integer value.
It is a scoping issue. if you use var inside a function, that variable will only exist in the scope of that function.
So what you could do is this:
var start;
function shapeAppear() {
start = new Date().getTime();
}
By removing var in the shapeAppear function, you're updating the var that is created outside the function.
Besides that as Rodney mentioned you call delay before shapeAppear which means that start is not defined when calling delay.
Hope that makes sense.
Related
This question already has answers here:
What is the JavaScript version of sleep()?
(91 answers)
Closed 2 years ago.
I'm trying to create something like slide show that is moved automatically after a delay.
I don't really understand how promises work so I find myself unable to create the sleep functinon.
Any solutions?
const startBtn = document.querySelector('.startBtn');
const box = document.querySelector('.box')
startBtn.addEventListener('click', () => {
for(var i = 1; i <= 20;i++){
//sleep(60000); <= the problem
box.style.transform = 'translateY(' + (-i * 100) + 'vh)';
}
});
Easiest you can do is use setTimeout:
setTimeout(function(){ alert("Hello"); }, 3000);
See: https://www.w3schools.com/jsref/met_win_settimeout.asp
Maybe you'll want to consider setInterval instead for your problem. In both cases you have to rework your solution a bit, the for loop won't help you much.
function sleep(delay){
return new Promise(resolve=>{
setTimeout(resolve,delay);
})
}
const fn = async () =>{
let pre = new Date()
console.log(pre);
await sleep(2000);
let after = new Date();
console.log(after - pre);
}
startBtn.addEventListener('click', async() => {
for(var i = 1; i <= 20;i++){
// sleep i*1000 seconds
await sleep(i* 1000);
box.style.transform = 'translateY(' + (-i * 100) + 'vh)';
}
});
This question already has answers here:
How to call a function in Javascript [duplicate]
(4 answers)
Closed 5 years ago.
While trying to move on to some intermediate/advanced Javascript concepts, I've run into a problem. In the following code, the object prototype and created objects seem to be functioning fine. But when I try to then use them in the function 'winner', the result always declares the winner as the second argument passed, regardless of their score. Here, Mike has a higher score(395) than Peter (206) and should be declared the winner. Also, the console is logging the message "Peter wins with a score of function () {
return (this.age * 5) + this.height;
}".
Any help understanding what I'm doing wrong would be greatly appreciated.
var player = {
name: 'Default',
age: 'Default',
height: 'Default',
score: function() {
return (this.age * 5) + this.height;
}
}
var Mike = Object.create(player);
Mike.name = 'Mike';
Mike.age = 67;
Mike.height = 60;
var Peter = Object.create(player);
Peter.name = 'Peter';
Peter.age = 30;
Peter.height = 56;
var winner = function(player1, player2) {
var player1score = player1.score;
var player2score = player2.score;
if(player1score > player2score) {
console.log(player1.name + ' wins with a score of ' + player1.score);
} else {
console.log(player2.name + ' wins with a score of ' + player2.score);
}
}
winner(Mike, Peter);
winner(Peter, Mike);
Replace
var player1score = player1.score;
var player2score = player2.score;
with
var player1score = player1.score();
var player2score = player2.score();
You have to call the function, if you just write player1.score you will get the body of the function.
This question already has answers here:
Stop setInterval call in JavaScript
(7 answers)
Closed 7 years ago.
Is it possible to have a invertal function that stop and starts if a variable is too high or too low
How can I make moneymaker stop when it reach 300?
I Tried with this code, but didn't get any results...
Code ex.
var money = 0;
var maxmoney = 300;
var moneymaker = window.setInterval(function(){
money = money + 1;
document.getElementById('money').innerHTML = money;
}, 1000);
function stopInter(){
if(hp >= maxhp)
clearInterval(regen);
}else{
setTimeout(function(){}, 1000);
}
}
var money = 0;
var maxmoney = 300;
var moneymaker = window.setInterval(function(){
if(maxmoney>money){
money = money + 1;
console.log(money);
}
document.getElementById('money').innerHTML = money;
}, 1000);
https://jsfiddle.net/4L2s5e0y/2/
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
Following this fiddle from this question, I wrote this bit of code:
var currentSlideCount = window.imgIds.length;
for (var i = 11; i < (currentSlideCount + 10); i++) {
// SET UP NEW SLIDE HTML
var newSlide = '<li><img id="apod' + i + '" class="rounded-corners apod-image"></li>';
$('#lightSlider').append(newSlide);
window.imgIds.push('apod'+i);
console.log(window.imgIds);
// GENERATE DATE
var date = new Date();
date.setDate(date.getDate() - i);
var day = date.getDate();
var month = date.getMonth();
var year = date.getFullYear();
console.log(year + "-" + month + "-" + day);
// GENERATE XML REQUEST
function foo(callback) {
var apodUrl = "https://api.nasa.gov/planetary/apod?concept_tags=True&date=" + year + "-" + month + "-" + day;
var apodXml = new XMLHttpRequest();
apodXml.open('GET', apodUrl, true);
apodXml.send(null);
// WHEN REQUEST IS READY
apodXml.onreadystatechange=function() {
if (apodXml.readyState==4 && apodXml.status==200) {
var apodParse = JSON.parse(apodXml.responseText);
callback(apodParse.url)
console.log(apodParse.url);
}
}
}
foo(function(result) {
var newSlideId = 'apod' + i;
document.getElementById(newSlideId).src = result;
});
Yet I'm still getting a Cannot set property 'src' of null console error on the img tag that was created long before its src attribute is being called on. And as far as I understand, I've set up the callback correctly. Why is this still not working?
First, you are declaring the function foo in a loop. While this is not leading to an error, it's bad practice. The function should be declared outside of the loop.
Second, the callback function passed into foo is invoked asynchronously (i.e., via AJAX). The variable i is assigned a value in the parent scope of the callback function and in a loop. The loop will have finished executing by the time the callback is invoked. When the callback is invoked, it will look up the scope chain to find the value of i and it will find i declared in the loop. i will be equal to the final value in the loop for which the loop conditional i < (currentSlideCount + 10) evaluates false and does not continue.
While this may be hard to follow, you can see what I mean by adding alert(i); to the callback function:
foo(function(result) {
alert(i);
var newSlideId = 'apod' + i;
document.getElementById(newSlideId).src = result;
});
You may be surprised to see that the alert will always display the same value for i.
To solve this problem, you need to use an immediately executing function to create a new scope where i is passed by value as the proper value you want.
Change this:
foo(function(result) {
var newSlideId = 'apod' + i;
document.getElementById(newSlideId).src = result;
});
To this:
foo(
(function(i) {
return function(result) {
var newSlideId = 'apod' + i;
document.getElementById(newSlideId).src = result;
}
})(i)
);
In JavaScript, scope is delineated at the function level. By using an immediately executing function, you are adding a new scope where i has been passed by value for the current iteration of the loop.
Variable scoping in JavaScript can be tricky to understand and your question hits right at one of the more complex scenarios. You may find it useful to review some other explanations of scoping in JavaScript.
Two problems there:
You're using a function declaration inside a control structure. You can't do that, it's invalid; some browsers will try to rewrite it for you as a function expression, but others will not. Function declarations are only valid at the top level of a scope, outside of all control structures. E.g., at global scope or at the top level of a function.
More importantly, the callback you're passing to foo has an enduring reference to the i variable, not a copy of it as of when the function was created. So they all see i as it is when they run, later, at the end of the loop.
Move your foo function out of the control structure, and ideally parameterize it, in particular passing it the i value that the callback should use. E.g.:
var currentSlideCount = window.imgIds.length;
for (var i = 11; i < (currentSlideCount + 10); i++) {
// SET UP NEW SLIDE HTML
var newSlide = '<li><img id="apod' + i + '" class="rounded-corners apod-image"></li>';
$('#lightSlider').append(newSlide);
window.imgIds.push('apod' + i);
console.log(window.imgIds);
// GENERATE DATE
var date = new Date();
date.setDate(date.getDate() - i);
var day = date.getDate();
var month = date.getMonth();
var year = date.getFullYear();
console.log(year + "-" + month + "-" + day);
foo(year, month, day, i, function(result, index) {
var newSlideId = 'apod' + index;
document.getElementById(newSlideId).src = result;
});
}
// GENERATE XML REQUEST
function foo(year, month, day, index, callback) {
var apodUrl = "https://api.nasa.gov/planetary/apod?concept_tags=True&date=" + year + "-" + month + "-" + day;
var apodXml = new XMLHttpRequest();
apodXml.open('GET', apodUrl, true);
apodXml.send(null);
// WHEN REQUEST IS READY
apodXml.onreadystatechange = function() {
if (apodXml.readyState == 4 && apodXml.status == 200) {
var apodParse = JSON.parse(apodXml.responseText);
callback(apodParse.url, index)
console.log(apodParse.url, index);
}
}
}
This question already has answers here:
How do I add a delay in a JavaScript loop?
(32 answers)
Closed 9 years ago.
Experts.
Javascript not producing desired delay effect.
From other questions, on SO I got to know that, problem is with settimeout and the way I am using it.
But still I am not able to comprehend, how Settimeout works.
So I am putting code here.
Need to use Javascript only, because of knowledge purpose.
Actually I am trying to clear my concepts about this, closure in javascript.
Are they kind of twisted things of Javascript?
var objImg = new Object();
var h;
var w;
var no = 100;
while (no != 500) {
setTimeout(function () {
size(no, no);
}, 2000);
/* it's get executed once, instead of repeating with while loop
Does it leave loop in mid? I get image with 500px height and
width, but effect is not acheived.
*/
no = no + 50;
}
function size(h, w) {
var objImg = document.getElementsByName('ford').item(0);
objImg.style.height = h + 'px';
objImg.style.width = w + 'px';
}
You have two problems :
no will have the value of end of loop when the callback is called
you're programming all your timeouts 2000 ms from the same time, the time the loop run.
Here's how you could fix that :
var t = 0
while (no != 500) {
(function(no) {
t += 2000;
setTimeout(function() { size(no,no);} ,t);
})(no);
no = no+50; // could be written no += 50
}
The immediately executed function creates a scope which protects the value of no.
A little explanation about (function(no) { :
The scope of a variable is either
the global scope
a function
The code above could have been written as
var t = 0
while (no != 500) {
(function(no2) {
t += 2000;
setTimeout(function() { size(no2,no2);} ,t);
})(no);
no += 50;
}
Here it's probably more clear that we have two variables :
no, whose value changes with each iteration and is 500 when the timeouts are called
no2, in fact one variable no2 per call of the inner anonymous function
Each time the inner anonymous function is called, it declares a new no2 variable, whose value is no at the time of call (during iteration). This variable no2 is thus protected and is used by the callback given to setTimeout.
Why not just use setInterval() instead?
var objImg = new Object();
var h;
var w;
var no = 100;
var myInterval = window.setInterval(function() {
size(no, no);
no = no + 50;
if (no >= 500) clearInterval(myInterval);
}, 2000);
function size(h, w) {
var objImg = document.getElementsByName('ford').item(0);
objImg.style.height = h + 'px';
objImg.style.width = w + 'px';
}
Your problem is with your size() function syntax & algorithm:
var objImg = new Object();
var h;
var w;
var no = 100;
var int = window.setInterval(function () {
size(no,no);
no += 50;
},2000)
function size(h, w) {
if (h == 500){
window.clearInterval(int);
return;
}
var height = h + 'px';
var width = w + 'px';
document.getElementsByName('ford').item(0).style.height = height;
document.getElementsByName('ford').item(0).style.width = width;
}
http://jsfiddle.net/AQtNY/2/