3

So I'm trying to master JavaScript and to practice I'm trying to make a reaction time test. The idea is very simple: you click on a button and after a random period of time the background changes colour and then you have to click on a second button which calls on a function that calculates your reaction time. Here is my JavaScript code:

function start(){
    console.log(start);
    var rndnr = (Math.round(Math.floor(Math.random() * 5) + 1)) * 1000);
    setTimeout(function timeout() {
      document.bgColor="ffff00";
      start = new Date();
    }, rndnr);
}

function stop() {
    var onclick = new Date();
    var time = onclick-start;
    var total;
    var avg;
    var count = 1;
    document.getElementById("try 1").innerHTML = time;
    total = total + time;
    avg = total / count;
    count = count + 1;
    document.getElementById("avg1").innerHTML = avg;
}

and these are my buttons:

<button id="button" onclick="start()" >start</button>
<button onclick="stop()">stop</button>

When I try to execute the script I get an error in my console log which says this: ReferenceError: start is not defined. Where have I gone wrong?

Jason Cust
  • 10,743
  • 2
  • 33
  • 45
Raiding_rider
  • 33
  • 1
  • 1
  • 3

6 Answers6

3

To ensure that the document knows about the start function, do something like:

window.start = function start(){ ... };

Or make sure to load your script before the handlers are assigned.

Secondly, don't try to set a value to start, since start refers to a function. Use startTime or another variable instead.

startTime = new Date();
Sebastian Nette
  • 7,364
  • 2
  • 17
  • 17
  • While these are good suggestions they don't answer the OP's question. Please refer to [my answer](http://stackoverflow.com/a/31141237/3194372) for the reason for the ReferenceError. – Jason Cust Jun 30 '15 at 15:15
  • @JasonCust They actually answer the question. `Uncaught ReferenceError: start is not defined` http://jsfiddle.net/sj4yz3a6/ http://jsfiddle.net/sj4yz3a6/1/ The OP didn't ask for his code to be fixed but for what is causing the issue. – Sebastian Nette Jun 30 '15 at 15:19
  • The `ReferenceError` arises due to the JS engine not being able to parse the code for the function due to an extra ')'. While what you mention is worth noting, the function is never declared because of the `Uncaught SyntaxError: Unexpected token )` error. I also fixed the code to point out other issues that would have impacted it after fixing that typo. – Jason Cust Jun 30 '15 at 15:23
  • The OP didn't mention the `SyntaxError`so it's most likely that his question contains a slightly altered version of his original code. – Sebastian Nette Jun 30 '15 at 15:26
  • Because of how inline JS works it is **the** reason for **both** errors. As the OP admits to being new to JS (or at least trying to master it) they probably didn't notice the `SyntaxError`. Or if they did notice it maybe they didn't think it was related. That said, it is **because** of that `SyntaxError` the function is never defined and therefore when the inline JS is evaluated it attempts to execute a function that does not exist resulting in the `ReferenceError`. I just edited [your fiddle](http://jsfiddle.net/sj4yz3a6/2/) to show this. Check the console output. – Jason Cust Jun 30 '15 at 15:32
  • You are just assuming that the OP is getting the `SyntaxError` while I assume that he does not. So my answer is just as correct and valid as any other correct answer until the OP confirms whether or not he was getting other errors. – Sebastian Nette Jun 30 '15 at 15:34
  • Lets agree to disagree :D – Jason Cust Jun 30 '15 at 15:35
  • I'm fine with that. Anyway it's up to the OP to pick the answer that fixes his problem. Cheers. – Sebastian Nette Jun 30 '15 at 15:36
3

You have quite a few typos in your code as well as some naming collisions and scope issues. This is your original code (aside from renaming stop to stopF since stop is a global function in a browser.

function start() {
  console.log(start);
  // THE REFERENCE ERROR STEMS FROM THIS LINE PREVENTING THE FUNCTIONS
  //  FROM BEING DEFINED
  var rndnr = (Math.round(Math.floor(Math.random() * 5) + 1)) * 1000);
  setTimeout(function timeout() {
    document.bgColor = "ffff00";
    start = new Date();
  }, rndnr);
}

function stopF() {
  var onclick = new Date();
  var time = onclick - start;
  var total;
  var avg;
  var count = 1;
  document.getElementById("try 1").innerHTML = time;
  total = total + time;
  avg = total / count;
  count = count + 1;
  document.getElementById("avg1").innerHTML = avg;
}
<button id="button" onclick="start()">start</button>
<button onclick="stopF()">stop</button>
<div id="try 1"></div>
<div id="avg1"></div>

If you click "Run code snippet" you will notice an error in the console:

 Uncaught SyntaxError: Unexpected token )

Because of this error, neither start nor stopF are defined. Therefore when the start button is clicked the inline JS would be evaluated and then attempt to find a non-existent start function resulting in a ReferenceError. Similarly if the stop button is clicked it will also log a ReferenceError for stopF.

Correcting some of the issues in the code gives:

// You need to have a way of referencing the `start` variable (now `startTime`)
//  between the `start` and `stop` functions.
// You also need to be able to keep state for `total` and `count` between
//  subsequent calls to `stop`
// These issues can be solved by using scope variables
//  (here they are in the IIFE scope of the wrapper function)
var startTime;
var total = 0;
var count = 0;

// You had a name collision here within the scope of `start`
//  you also had attempted to use a variable named `start`
// Now the variable is called `startTime`
function start() {
  // You had an extra ')' in your expression assignment for `rndnr`
  var rndnr = (Math.round(Math.floor(Math.random() * 5) + 1) * 1000);
  setTimeout(function timeout() {
    document.bgColor = "ffff00";
    startTime = new Date();
    // Since setTimeout is an async function console.log would be undefined
    //  until this function runs
    console.log(startTime);
  }, rndnr);
}

function stop() {
  var onclick = new Date();
  var time = onclick - startTime;
  var avg;
  total += time;
  avg = total / ++count;

  // You shouldn't include spaces in ID values as it can be confusing
  //  if this was intentional
  document.getElementById("try1").innerHTML = time;
  document.getElementById("avg1").innerHTML = avg;
  document.bgColor = "ffffff";
}
<button id="button" onclick="start()">start</button>
<button onclick="stop()">stop</button>
<div id="try1"></div>
<div id="avg1"></div>
Jason Cust
  • 10,743
  • 2
  • 33
  • 45
1

Edited:

Here is a working version of your code (only the stop button needs the tags "try 1" and "avg")

http://jsfiddle.net/2q84yvzu/

The problem was on the extra ) on:

var rndnr = (Math.round(Math.floor(Math.random()*5)+1))*1000);

This is the correct version:

var rndnr = (Math.round(Math.floor(Math.random()*5)+1))*1000;

I changed the way of you bind the events to the elements, is not a good practice to embed the events inline. Instead try the next approach:

document.getElementById('start').onclick=function(){start();};
document.getElementById('stop').onclick=function(){stop();};

For more info on this, here is another question:

Inline onclick JavaScript variable

Community
  • 1
  • 1
HolloW
  • 720
  • 11
  • 21
1
var rndnr = (Math.round(Math.floor(Math.random()*5)+1))*1000);

syntax error,it should be

var rndnr = (Math.round(Math.floor(Math.random()*5)+1))*1000;
Ben Zhong
  • 9
  • 3
0

You need to rename variable start inside setTimeout function, because you override function start with date value after the first call of start() function.

function f(){
    setTimeout(function(){ f = 1; }, 1000);
}

console.log(f); // function

f();

setTimeout(function(){ 
  console.log(f); // 1
}, 1100);
Vladimir
  • 342
  • 1
  • 8
-2
console.log(start); 

is wrong

It has to be

console.log("start"); 

or you have to create the variable start

var start = "put anything in here";
console.log(start);
Kbi
  • 384
  • 2
  • 16