I'm going through a JavaScript book and have been executing code samples using Node.js. I've been writing files then running node file.js.
Normally, I use semicolons writing JavaScript, but I'm following the book's style.
I came across a error while executing one of the code samples, and I can't figure out why it happens.
Executing:
var x = 2
var y = 3
(x == 2) && (y == 3)
(x > 3) || (y < 3)
Results in the error:
TypeError: 3 is not a function
If I add a ; after line 2, e.g.
var x = 2
var y = 3;
(x == 2) && (y == 3)
(x > 3) || (y < 3)
It results in the error:
TypeError: (y == 3) is not a function
However, if I place a ; after the third line as well, e.g.
var x = 2
var y = 3;
(x == 2) && (y == 3);
(x > 3) || (y < 3)
Things work fine.
Or if I run each line (individually) in the Node.js command line, everything works fine.
It's probably just my misunderstanding of Node.js or JavaScript. But I couldn't find another similar situation online.
I'm using OS X 10.11.1 and Node.js v5.2.0 (installed through Homebrew).
This would happen in any JavaScript environment, not just node. There are specific rules as to when semi-colons can be omitted. This is why the majority if the community advocates against omitting semi-colons.
This is being executed as a single statement:
var y = 3
(x == 2) && (y == 3)
(x > 3) || (y < 3)
Statements are delineated by context (or semi-colon), not by whitespace or newlines.
var y = parseInt('10px');
is the same as
var y = parseInt
('10px');
is the same as
var y = parseInt ('10px');
So when you try to execute var y = 3 (x == 2), the JIT is interpreting 3 as a function, due to the parenthesis that follow it.
If the next line starts with a '(' then the statement is not terminated by a new line. Therefore, you need a ';' or some other token to specify that the statement has ended.
You can read more about javascript and semicolons here and here.
Your first error is occurring because the code is being interrupted as:
var y = 3(x == 2)
The second error if from the code being interrupted as:
(y == 3)(x > 3)
These are invalid.
Adding the semicolons changes your code to
var y = 3;(x == 2)
and
(y == 3);(x > 3)
These are valid.
Javascript uses the semicolon and not newline to denote the end of a statement and the possible beginning of another. So, when you tried to execute:
var x = 2
var y = 3
(x == 2) && (y == 3)
(x > 3) || (y < 3)
It interpreted it as:
var x = 2 var y = 3(x==2) && (y==3)(x > 3) || (y<3)
Which seemed like you were trying to initialize y with the value of function 3(x=2) which is wrong syntax and semantics for a function declaration in javascript.
When you put a semicolon after the second line, it interpreted lines 1 and 2 as you meant them to be interpreted, but again a similar issue arose in lines 3 and 4, which were fixed once you added the semicolons.
You only need semicolons where javascript cannot tell the end of one statement and the beginning of another. You can omit them, but the general rule is something like this.
As you can see here,
The source
a = b + c
(d + e).print()
is not transformed by automatic semicolon insertion, because the parenthesised expression that begins the second line can be interpreted as an argument list for a function call:
a = b +c(d + e).print()
In the circumstance that an assignment statement must begin with a left parenthesis, it is a good idea for the programmer to provide an explicit semicolon at the end of the preceding statement rather than to rely on automatic semicolon insertion.
It's a well known pitfall when coding without semicolons in JavaScript and that also behaves the same for Node.js.
Related
I am a beginner in JavaScript programming and this is my first project. I am trying to find the factors of a quadratic expression using the standard factorization method. I have explained the logic I used in the code as a comment at the beginning of the main JavaScript function and I have also listed the bugs I have detected so far at the end of the code. I depended solely on my logic based on previous exercises I have done to write this code, so I am hoping to learn a lot from your corrections. I don't know where the bugs are coming from in the code. I would be very grateful if you can help me figure out any. Thank you.
<!DOCTYPE html>
<html>
<head>
<title>Factorization of Quadratic Expression</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<div id="box">
<div id="inner">
<p>Quadratic Equation <span id="warning">MUST</span> be in this format
<span id="format">ax<sup>2</sup> + bx + c</span></p>
<p>Use the caret symbol (<span id="caret">^</span>) for exponent, e.g x^2</p>
<input type="text" placeholder="Enter quadratic equation" id="equation" required/><br/>
<br/>
<button id="solve">Answer</button>
<p id="solution"></p>
</div>
</div>
<script type="text/javascript">
// get button and paragraph to display solution
let solution = document.getElementById('solution');
let solve = document.getElementById('solve');
// solve quadratic equation
solve.onclick = function() {
/* This is the main function of the code that finds the factors a quadratic expression.
I assume you already have an understanding of quadratic expressions but I will
explain
the logic I used in the code. Assuming you have a quadratic expression f(x),
f(x) = x^2 - 4x + 4
I first multiplied the coefficient of x^2 which is +1 in this case with the constant
which
is +4. Then I find two numbers whose product gives the value of the constant +4 and
whose
sum gives the value of the coefficient of x which is -4. The numbers are -2 and -2.
Then I substitute the numbers with the value of the coefficient of x adding the
literal.
f(x) = x^2 - 2x - 2x + 4
Next is grouping the first two quadratic coefficients and the last two using
parentheses.
f(x) = (x^2 - 2x) - (2x - 4)
The arithmetic symbol of the constant changes because once you expand it will give
you the former expression.
Next is to finding the greatest common divisors of both groups and simplify.
f(x) = x(x - 2) - 2(x - 2)
Next is getting the common factors.
f(x) = (x - 2)(x - 2) // Final answer
Last line of code outputs the answer and it is the biggest challenge I am having
because it seems I can only display a specific arithmetic symbol '+' (I chose to use
this because I wrote the code using an all positive quadritic expression) in this
case though it varies depending on the quadratic expression, like the one I used in
this comment. */
// get expression from input
let equation = document.getElementById('equation').value;
// validate expression (Only did this for fun and to get the feel of a real-world
project)
// if input was an empty string
if(equation === '') {
solution.innerHTML = 'Error: No expression found! Please fill out the input field';
}
// if a symbol is missing or is there is none
else if((equation.match(/(\+|\-)/g) === null) || (equation.match(/(\+|\-)/g).length < 2))
{
solution.innerHTML = 'Error: Missing symbol in expression';
}
// if the expression is not in the specified format
else if((equation.match(/\s/g).length < 2) || (equation.match(/\s/g).length > 2)) {
solution.innerHTML = 'Error: Missing or excess whitespace character in expression';
}
// if the exponent of x is not 2
else if(equation[equation.indexOf('^') + 1] !== 2) {
solution.innerHTML = 'Error: Exponent of x must be equal to 2';
}
// none of these validations work by the way not sure why
// get coefficient of x^2, x and the constant in the equation from input
array = equation.trim().split(''),
sign1 = array.indexOf('+'),
sign2 = array.lastIndexOf('+'),
getCoefficient_x2 = array.slice(0, array.indexOf(sign1 !== -1 ? '+' : '-') +
2).join(''),
getCoefficient_x = array.slice(array.indexOf(sign1 !== -1 ? '+' : '-') + 2,
array.lastIndexOf('+') - 1).join(''),
getConstant = array.slice(array.lastIndexOf(sign2 !== -1? '+' : '-') + 2).join(''),
cox2 = parseInt(getCoefficient_x2) || 1,
cox = parseInt(getCoefficient_x) || 1,
c = parseInt(getConstant);
// solving quadratic equation
let product = cox2 * c,
sum = cox,
factors = getFactors(product),
sum_product = [],
_gcd = 0,
gcd_ = 0,
cfactor = [];
// get factors whose product is equal to the constant and whose sum is equal to
coefficient of x
for(let i = 0; i < factors.length; i++) {
for(let j = 0; j < factors.length; j++) {
if((factors[i] * factors[j] === product) && (factors[i] + factors[j] === sum)) {
sum_product = [factors[j], factors[i]];
}
}
}
// grouping
// get greatest common divisor of both groups
_gcd = gcd(cox2, sum_product[0]);
gcd_ = gcd(sum_product[1], c);
// finding the common factors of the expression
/* since the computer never makes a mistake I will only factor the first grouping as this
will determine the other. */
cfactor.push(cox2 / _gcd, sum_product[0] / _gcd);
// expression of factorization is given as:
solution.innerHTML = `(${_gcd > 1 ? _gcd : ''}x + ${gcd_})\
(${cfactor[0] > 1 ? cfactor[0] : ''}x + ${cfactor[1]})`;
}
// function to get all negative and positive factors of a number
function getFactors(number) {
var factors = [],
i = 0;
if(number === undefined) number = 0;
for(i = -number; i <= number; i++) {
if(number % i === 0) factors.push(i);
}
return factors;
}
// function to get the greatest common divisor of two numbers
function gcd(num1, num2) {
var numFac = [], gcd, maxNum = Math.max(num1, num2);
for(let n = 1; n <= maxNum; n++) {
if(num1 % n == 0 && num2 % n == 0) {
numFac.push(n);
}
}
return Math.max(...numFac);
}
// Bugs
/* (1) Outputs an unexpected value if the coefficient of x is greater than the constant.
(2) Outputs an unexpected value if the expression uses a negative number.
(3) Outputs an unexpected value if coefficient of x and the constant have no common
factors to determine the the sum and product respectively.
(4) None of the validation codes works.
(5) I am not sure how I can vary the signs of the symbol depending on the give expression.
*/
</script>
</body>
</html>
About the 4th bug: Your validations are working, the inner content of solution is being modified, but your final answer is overwriting it. You could add a boolean variable valid = false if one of your validations returns an error, and before changing the innerHTML of solution for the final answer, check if valid = true, if it is not, don't print your final answer.
Like this:
var valid = true;
if (equation === '') {
solution.innerHTML = 'Error: No expression found! Please fill out the input field';
valid = false;
}
// if a symbol is missing or is there is none
else if ((equation.match(/(\+|\-)/g) === null) || (equation.match(/(\+|\-)/g).length < 2)) {
solution.innerHTML = 'Error: Missing symbol in expression';
valid = false;
}
// if the expression is not in the specified format
else if ((equation.match(/\s/g).length < 2) || (equation.match(/\s/g).length > 2)) {
solution.innerHTML = 'Error: Missing or excess whitespace character in expression';
valid = false;
}
// if the exponent of x is not 2
else if (equation[equation.indexOf('^') + 1] !== 2) {
solution.innerHTML = 'Error: Exponent of x must be equal to 2';
valid = false;
}
And in your final answer:
if (valid) {
solution.innerHTML = `(${_gcd > 1 ? _gcd : ''}x + ${gcd_})\
(${cfactor[0] > 1 ? cfactor[0] : ''}x + ${cfactor[1]})`;
}
Thank very much. I understand. I'm enlightened, it slipped my mind that the code
will continue to the next line even if one of the if statements is true. I might have thought I was returning the error message. Thanks again.
I am currently studying if condition statement and it is one of my weakest topic ever. Here in this code below, there are two if conditions and I would like to know, how do we find the output of this? I know how to get the output when there is one if. But what about having two if?
function exercise3(){
var x, y, z;
x = 20;
y = 30;
z = 50;
if ((x - 10) < y) {
if (y - 5 > x) {
alert (z - x);
}
else {
alert (z - 5);
}
}
}
exercise3();
This is referred as Nested If statement. Basically you deal with the most outer block first before the going into the inner block. You would only go into the inner block if the condition in the statement is true.
Your statement condition is true
if ((x - 10) < y) {
...
}
Hence you would proceed to read through.
Take note generally to make it more readable better use If else statements rather than if alone as the execution will proceed to check the next if statement with is actually block one and block two (one by one) bringing about slow execution in long written statements.
Ref: https://www.w3schools.com/js/js_if_else.asp
Cheers, happy learning and happy coding.
That is the same as this, if it helps you understand better. The below snippet is just for example purpose, do not follow that. You need to use nested if conditionals.
function exercise3(){
var x, y, z;
x = 20;
y = 30;
z = 50;
// The first if and nested if from your snippet
if ((x - 10) < y) && (y - 5) > x) {
alert(z - x);
}
// The first if and nested else from your snippet
if ((x - 10) < y && (y - 5) <= x) {
alert (z - 5);
}
}
exercise3();
Within my project I have a character that automatically walks down the screen. I want to detect whenever the character hits a certain dungeon (each "dungeon" is a div with some text inside).
Here is my code in a simplified format:
//call the function
console.log(isCollide(characterData[0][0], document.getElementsByClassName("Dungeon_Wrapper_Room")[a])));
var isCollide = function(a, b) {
//Used to parse get the x/y pixel coordinates by removing the "px" at the end of the string.
var aTOPstr = a.style.top;
var aTOP = (parseInt(aTOPstr.slice(0, aTOPstr.length-2)));
var aLEFTstr = a.style.left;
var aLEFT = (parseInt(aLEFTstr.slice(0, aLEFTstr.length-2)));
var bTOPstr = b.style.top;
var bTOP = (parseInt(bTOPstr.slice(0, bTOPstr.length-2)));
var bLEFTstr = b.style.left;
var bLEFT = (parseInt(bLEFTstr.slice(0, bLEFTstr.length-2)));
console.log(((aTOP + 32) > (bTOP))+" "+(aTOP < (bTOP - 32))+" "+((aLEFT + 32) > bLEFT)+" "+(aLEFT < (bLEFT + 50)));
return (
!((aTOP + 32) < (bTOP)) ||
(aTOP > (bTOP + 50)) ||
((aLEFT + 32) < aLEFT) ||
(aLEFT > (aLEFT + 50))
);
};
The character image was created dynamically (in the end I'll use a for loop to run through an array of characters, each with this detection).
var characterData = [
[document.createElement("img"), {/*Misc. Character Data Goes Here*/}]
];
characterData[0][0].src = "images/characters/default.png";
characterData[0][0].style.position = "relative";
characterData[0][0].style.left += ((50-32)/2)+"px";
characterData[0][0].style.top += (-(50-32+25))+"px";
characterData[0][0].id = "character0";
tavernBox.appendChild(characterData[0][0]);
My HTML:
<div id="Town_Wrapper">
<div id="townBoxWrapper">
<div id="tavernBox">
<!-- Characters are appended here -->
</div>
</div>
</div>
<div id="Dungeon_Wrapper">
<div class='Dungeon_Wrapper_Room'>Boss
<!--Box character is being detected with-->
</div>
</div>
I've based my hit detection off the answer I found here: https://stackoverflow.com/a/7301852/7214959 but still am having no success.
I have absolutely no clue what is wrong with it. I've tried switching the < around and other functions but still can't find anything. I've also tried going from relative to absolute positioning and still got nothing. The isCollide function needs to return true or !false to indicate it has collided but each section of the if statement always returns "false" and there is never a single "true".
JSFiddle (contains debugging for console and alert): https://jsfiddle.net/drfyvLng/
Solved: The selected answer solves the issue presented in the jsfiddle. Within my own code I had to turn the certain dungeon into absolute positioning and find its location use .offsetTOP and .offsetLEFT. Additionally I made the return formula detect when the character is inside the box rather than when it isn't.
There were a few issues with the JSfiddle.
This was evaluating to null because there's no top set in the css style.
var bTOPstr = b.style.top;
Update your CSS to this and that part is covered.
<div class='Dungeon_Wrapper_Room' style="background-color: yellow; min-height:50px; top:0px; bottom:50px; left:0px; right:100px">
Then your if statement that checks collision is different to the one you based it off, be careful when copying code!
!((aTOP + 32) < (bTOP)) ||
(aTOP > (bTOP + 50)) ||
((aLEFT + 32) < aLEFT) ||
(aLEFT > (aLEFT + 50))
aLeft + 32 < aLeft should be aLeft + 32 < bLeft
aLeft > aLeft + 50 should be aLeft > bLeft + 50
Finally, you need another bracket on the if statement. The answer your based it off is checking '!' on the entire expression, yours just uses the first line.
So now it looks like this.
!(((aTOP + 32) < (bTOP)) ||
(aTOP > (bTOP + 50)) ||
((aLEFT + 32) < bLEFT) ||
(aLEFT > (bLEFT + 50)))
Which should work.
What I would like to do is replace the two if statements with a single mathematical formula. I can't for the life of me figure out how, as mathematics was never my strong point. Any advice would be greatly appreciated.
<script>
var x, y, z;
x = 200;
y = 100;
i = 0;
while(z != y) {
i++;
if (x < y) z = x + i;
if (x > y) z = x - i;
document.write(z + "<br>");
}
</script>
Edit: the real code looks like this. It's not too pretty, was hoping I could shrink it down to two lines.
if (prevposX < newposX) posX = prevposX + animStep_;
if (prevposX > newposX) posX = prevposX - animStep_;
if (prevposY < newposY) posY = prevposY + animStep_;
if (prevposY > newposY) posY = prevposY - animStep_;
Edit:
It has been a while, but I believe the Modulus (%) operator would have helped me. I've now moved on to a library to do graphics for me so I didn't need it in the end.
You can make use of a ternary operator
z = x + ((x<y) ? i : -i)
This assumes that when x >= y then you want to -i. If you want to stick exactly to your original you need a second ternary operator, which gets a bit messy:
z = x + ((x<y) ? i : ((x>y) ? -i : 0))
Frankly, it might be clearer to just keep it on 2 lines with 2 if statements like you already have.
I seem to handle special cases like this somewhat frequently. There's got to be a more concise syntax or construct:
var x = solveForX(); /* some slow calculation here */
if (x < 0)
{
x = 0;
}
This is equivalent, but doesn't feel any more elegant:
var x;
x = (x = solveForX()) < 0 ? 0 : x;
Maybe there's a bit shift trick?
Update: I ran some benchmarks to compare my two favorite answers - the one I accepted, and Peter Ajtai's. Turns out Peter's is quite a bit faster! Running 1,000,000 iterations of each (I also ran a version that caches Math.max to see how much time the lookup contributed) shows that Peter's runs in under half the time of the Math.max version, even with max caching.
That said, even the "slowest" method is still quite fast.
How about
var x = Math.max(solveForX(), 0);
Something like:
x = Math.max(0, solveForX());
(x < 0) && (x = 0);
Edit: Removed the if statement. Thanks Andreas.
This is one line, and it's clear what it does (in my personal opinion) - if you're familiar with boolean short circuit evaluation.
The above makes use of boolean short circuit evaluation. This can be very useful in certain situations (especially pointer arithmetic in C++, but boolean short circuit evaluation also works in Javascript).
x = 0 only evaluates if x < 0.
Here are two examples:
This alerts 1:
<script type="text/javascript">
var x = 1;
(x < 0) && (x = 0);
alert(x);
</script>
This alerts 0:
<script type="text/javascript">
var x = -1;
(x < 0) && (x = 0);
alert(x);
</script>
I'd decorate the original solveForX function.
function returnNonNegative(fn) {
function _f() {
var x = fn();
if (x < 0) {
x = 0;
}
return x;
}
return _f;
}
solveForX = returnNonNegative(solveForX);
In this particular case, using Math.max seems to be fine, but this pattern provides a generic solution for this type of problems.
The accepted answer is perfect. If you want to accomplish the same without a function call, I believe that this is most concise:
var x;
(x = solveForX()) > 0 || (x = 0);
(In Safari, this implementation is a whole 7% faster than Math.max(), which is probably not worth caring about)
I think that this way is pretty nice!
var x = Math.max(solveForX(), 0);
Good luck!