+ 2
Why will this window.onload function not run?
When I run this program, it displays the first couple blocks of code that are not in the window.onload function, but the window.onload function itself will not run. Why is this? https://code.sololearn.com/WS5nmS4omS32/?ref=app
17 ответов
+ 4
Your code (same with 'secondNumber'):
firstNumber = prompt(name + ", what is your first number?");
console.log(firstNumber);
firstNumber += parseInt(firstNumber);
if (!isNaN(firstNumber)) ...
The prompt() function return a String.
You log the value: it's ok
Then the line where you try to parse to int: num += parseInt(num) wich is equivalent to num = num + parseInt(num) ^^
Do you see the mistake ?
You store in your variable the concatenation of the String with the newly parsed Integer...
My suggestion to fix it:
firstNumber = Number(prompt(name + ", what is your first number?"));
console.log(firstNumber);
// firstNumber += parseInt(firstNumber);
if (!isNaN(firstNumber)) ...
... because Number() allow you to use integer as well as floating point values, and mostly because I was debugging your code step by step, without testing it before posting (it was very late for me, and not my first intention to correct your code -- my first post was intented to let yourself correct it)
But anyway, another way to fix it would be:
firstNumber = prompt(name + ", what is your first number?");
console.log(firstNumber);
firstNumber = parseInt(firstNumber);
if (!isNaN(firstNumber)) ...
(just removing the '+' in front of '=')
+ 2
/*
Now that you seems to have corrected your code by following advice of @Faisal, your code better works, but still remain an error, due to the local variable used in each functions, which are not accessible in other functions... To fix this, you need to declare your variables in a shared variable scope accessible from the functions requiring them (best practice is to avoid use of global scope, wich is easily doable by using a wrapper function assigned to the onload event:
*/
var value = 42; // this variable is defined (keyword 'var') in the global scope, and could be accessible from anywhere
onload = function() {
/* a function define a new local scope, where variables cannot be accessible from outside (here the global scope) */
var localvalue = 42; // defined in the function localscope, and is unreachable from global scope
function localtest() {
var privatevalue = 42; // defined in function localscope, so private to this function
console.log(value+''); // 42
console.log(localvalue+''); // 42
console.log(privatevalue+''); // 42
}
localtest();
console.log(value+''); // 42
console.log(localvalue+''); // 42
console.log(privatevalue+''); // undefined
}
console.log(value+''); // 42
console.log(localvalue+''); // undefined
console.log(privatevalue+''); // undefined
+ 2
Isn't that what I did? Creating a wrapper function that surrounds all the functions assigned to the window.onload event?
+ 2
Read closer my answer: I don't say you didn't create a wrapper function that surrounds all your code, but I say that's not enough to make your code working, and I explain why to let you be able to correct it... Don't you get a << Uncaught ReferenceError: firstNumber is not defined line 46 >> when you try to run your code? My previous post would help you to understand and fix it ^^
+ 2
I see what you are saying, but the variables I want to make global are prompts, and I want them to do specific things like if its not a number, end the program. I can't do that if they are global because then they will run no matter what
+ 2
You don't have to make them global, but local to the wrapper function, and only declare them in this root-local scope, and then you assign the return value to the root-local variable in each of the specific function, without making them private to these specific functions:
window.onload = function() {
var firstNumber;
var secondNumber;
function numerics() {
firstNumber = prompt(name + ", what is your first number?");
console.log(firstNumber);
firstNumber += parseInt(firstNumber);
if (!isNaN(firstNumber)) {
numbers();
}
else {
alert("That is not an acceptable value, restart the program to try again");
}
}
function numbers() {
secondNumber = prompt("What is your second number, " + name);
console.log(secondNumber);
secondNumber += parseInt(secondNumber);
if(!isNaN(secondNumber)) {
operate();
}
else {
alert("That is not an acceptable value, restart the program to try again");
}
}
function operate() {
// here you could have 'operation' private to this function scope, as you don't have to access it from another function ^^
var operation = prompt(name + ", what would you like to do to your two numbers?");
console.log(operation);
if (operation === "+") {
alert(name + " , the answer is " + firstNumber + secondNumber);
}
else if (operation === "-") {
alert(name + " , the answer is " + firstNumber - secondNumber);
}
else if (operation === "*") {
alert(name + " , the answer is " + firstNumber * secondNumber);
}
else if (operation === "/") {
alert(name + " , the answer is " + firstNumber / secondNumber);
}
else {
alert("That is not an acceptable operator, restart the program to try again");
}
}
numerics();
numbers();
operate();
}
+ 2
Also, before add some parenthesis to avoid concatening string instead of doing math:
if (operation === "+") {
alert(name + " , the answer is " + (firstNumber + secondNumber));
}
else if (operation === "-") {
alert(name + " , the answer is " + (firstNumber - secondNumber));
}
else if (operation === "*") {
alert(name + " , the answer is " + (firstNumber * secondNumber));
}
else if (operation === "/") {
alert(name + " , the answer is " + (firstNumber / secondNumber));
}
+ 2
and convert explicitly string to numbers:
num = Number(prompt());
+ 2
and remove the lines:
firstNumber += parseInt(firstNumber);
secondNumber += parseInt(secondNumber);
+ 2
And finally, you should remove the two last line calling numbers() and operate(), as only numerics() have to be called (then it will chain both other functions)...
Whole fixed code would be:
var name = prompt("What is your name?");
console.log(name);
alert(name + ", my name is Mr. Calculator, I can help you out with your math problems!");
window.onload = function() {
var firstNumber;
var secondNumber;
function numerics() {
firstNumber = Number(prompt(name + ", what is your first number?"));
console.log(firstNumber);
if (!isNaN(firstNumber)) {
numbers();
}
else {
alert("That is not an acceptable value, restart the program to try again");
}
}
function numbers() {
secondNumber = Number(prompt("What is your second number, " + name));
console.log(secondNumber);
if(!isNaN(secondNumber)) {
operate();
}
else {
alert("That is not an acceptable value, restart the program to try again");
}
}
function operate() {
var operation = prompt(name + ", what would you like to do to your two numbers?");
console.log(operation);
if (operation === "+") {
alert(name + " , the answer is " + (firstNumber + secondNumber));
}
else if (operation === "-") {
alert(name + " , the answer is " + (firstNumber - secondNumber));
}
else if (operation === "*") {
alert(name + " , the answer is " + (firstNumber * secondNumber));
}
else if (operation === "/") {
alert(name + " , the answer is " + (firstNumber / secondNumber));
}
else {
alert("That is not an acceptable operator, restart the program to try again");
}
}
numerics();
}
+ 2
On the other hand, division and multiplication doesn't require adding parenthesis because of operator precedence, since 'firstNumber' and 'secondNumber' are really numbers:
string + num1 + num2
is evaluated from left to right, so equivalent to:
( string + num1 ) + num2
so, result of parenthesis is a String concatened with the first number, and then newstring + num2 is again the result of concatenation of newstring and second number...
string + num1 - num2
is also evaluated from left to rigth, as:
(string + num1) - num2
same problem, different result: you first get a newtring, and then you're trying to do newstring - num2 wich result to NaN (minus operator have nothing to to with Strings, so newstring is implicitly converted to number, but resulting NaN, so the you get NaN - num2 wich equal also NaN...
string + num1 * num2
is where comes operator precedence: rule from left to right is still true, but '*' operator have higher precedence than '+' (wich share same precedence as '-'), so the operation is (implicitly) equivalent this time to:
string + (num1 * num2)
wich is what I advise to do explicitly, but well working if you doesn't, as now you first do numeric operation (multiplication), then concatenate the result to the string...
string + num1 / num2
is almost identical, as '/' (division) share the same precedence than '*' (multiplication), so is implicitly what you want to do, as for multiplication, but advised to explicitly put parenthesis ^^
+ 2
Wow, this was really helpful. Thanks!
+ 1
It's not that the window.onload function is not running, but the functions within it are not running. The problem with your code is that you're declaring three functions within the onload one, but none of them are being called. In the window.onload function, try calling the first function and see if that works.
+ 1
Oh, so you can declare variables globally and define them locally and still have the value stored in the global variable?
+ 1
Thank you!
+ 1
But wait, why would I remove the parseInt statements? They convert the string into a number, which is what I want
+ 1
Actually I'm not sure about parseInt. I don't know exactly why, but the operations are behaving strangely. Something is doubling both the numbers, the + command seems to concatenate the variables instead of adding them, * doubles the numbers and then multiplies them, and - returns NaN. the / operator seems to work fine though