Parameters will not be hoisted and will hit temporal dead zone? - javascript

function bar(x=y, y=2) {
return [x, y];
}
bar();//uncaught reference: y is not defined
I can't understand why the above code will hit exception. If from other languages it make sense because flow of programs are important and we can't reference to y because y is not created yet and it would be resulted in compilation error. However this is JS, both x and y should equally be hoisted first and such reference shouldn't throw exception. I would expect the pseudo-code to be similar like below?
x=y
var x;
var y;
console.log(x,y); //undefined undefined (which is fine as no value but instead of throwing exception)
UPDATES:
function bar() {
var x = arguments.length >= 1 ? arguments[0] : y;
{
var y = arguments.length >= 2 ? arguments[1] : 2;
return [x, y];
}
}
console.log(bar());//[undefined, 2]

Your assumption is wrong, they're not hoisted like that. It's more like:
function bar() {
let x = arguments.length >= 1 ? arguments[0] : y;
{
let y = arguments.length >= 2 ? arguments[1] : 2;
return [x, y];
}
}
The scope of each variable default value only includes the variables to the left of it, not the variables to the right.

Related

Identical function leads to different outcomes in different languages

I wrote a function in javascript that is supposed to return the lowest prime number larger than x. Instead it get's caught in indefinite recursion.
function next_prime(x) {
if (x <= 1) {
return 2;
}
y = 2;
z = x + 1;
while(true) {
if (z % y == 0) {
z++;
y = 2;
continue;
}
if(y * y > z) {
return z;
}
y = next_prime(y);
}
}
I didn't understand what was wrong, so I implemented the same function in python, where it worked just fine.
def next_prime(x):
if x <= 1:
return 2
y = 2
z = x + 1
while True:
if z % y == 0:
z += 1
y = 2
continue
if y * y > z:
return z
y = next_prime(y)
I looked over both functions and I'm sure that they are identical, yet in python it works and in javascript it doesn't.
Allthough appreciated, I'm not necessarily looking for help with this specific problem, I'm more so interested in what is actually going on here.
I think the problem is that you are not declaring your variables correctly. In JavaScript, you have to use the keywords let and const - which stand for reassignable and not reassignable variables - when declaring a new variable. When using let in lines five and six, the function works just fine.
You should use strict mode to avoid this common mistake of javascript beginners.
your actual js code with 'use strict'; is rejected :
'use strict';
console.log( next_prime(7) ) // never run on strict mode, otherwise make an infinite loop
function next_prime(x) {
if (x <= 1) {
return 2;
}
y = 2;
z = x + 1;
while(true) {
if (z % y == 0) {
z++;
y = 2;
continue;
}
if(y * y > z) {
return z;
}
y = next_prime(y);
}
}
same code in correct javascript syntax :
'use strict';
console.log( next_prime(7) ) // -> 11
function next_prime(x)
{
if (x <= 1) return 2
;
let y = 2, z = x + 1 // declare y and z as locale
;
while(true)
{
if (z % y == 0)
{
z++;
y = 2;
continue;
}
if (y**2 > z) return z
;
y = next_prime(y);
}
}
explanation : your code is recursive, inside call will change y and z value on parent callers and make an infinite loop

Function to create new array producing undefined

I am trying to write a program that creates an array and populates it with a range of numbers. The function range's x, y, z variables correlates to the start number, the end number, and the number value of each step. My goal is produce an array with all the numbers between (and including) x and y that is created with each step. Here is the code:
let newarray = []
function range (x, y, z){
if (x === undefined || y === undefined || z === undefined || (x > y) || (z < 0)) {
return newarray; // returns empty array if x, y, or z is undefined, x is greater than y or z is a negative integer
}
else if (y > x) {
for (x; x < y; x = x += z) {
newarray.push(x); //pushes x into an array then adds z into x and loops until x exceeds y
}
}
else {
return newarray; //prints out new array
}
}
console.log(range(0, 10, 2));
console.log(range(10, 30, 5));
console.log(range(-5, 2, 3));
right now it is producing undefined for all three numbers. My research suggests something about asynchronicity? I'm not sure what that means.
A few things are at play here:
newArray should be defined inside the function scope rather than as a global variable. Otherwise, subsequent calls to the function will keep appending onto the same array, which is likely not your intention (and if it was, there's array.concat() for that).
Your last else is unreachable, so the function will either return an empty array for input failing your validation or return undefined when control reaches the end of the function after populating the array in the else if block.
x = x += z is probably intended as x += z.
You should disallow z === 0 otherwise you'll wind up with an infinite loop.
Normal JS style is to camelCase variable names.
Additionally, I find it's easier to write positive conditionals than negative conditionals. In this case, enumerating what arguments are allowed seems cleanest. This approach enables you to only have one return statement and fewer conditional branches, mitigating potential confusion.
Here's a version that addresses these issues:
function range(x, y, z) {
const newArray = [];
if ([x, y, z].indexOf(undefined) < 0 && x < y && z > 0) {
for (; x < y; x += z) {
newArray.push(x);
}
}
return newArray;
}
console.log(range(0, 10, 2));
console.log(range(10, 30, 5));
console.log(range(-5, 2, 3));
Note that the section where you check else if (y > x) does not have a return. When this condition is true, your function returns undefined. To fix the problem, just add return newarray; as the last line in the function. Then remove all other lines with return new array;.
The else block is not required as it will be unreachable and will
return undefined.
Corrected x = x + z from x = x += z.
The array declaration was outside, so every time the old data will be
appended with newer data from the for loop.
function range (x, y, z){
let newarray = [];
if (x === undefined || y === undefined || z === undefined || (x > y) || (z < 0)){
return newarray;
}
else if (y > x) {
for (x; x < y; x = x + z){
newarray.push(x);
}
}
return newarray;
}
console.log(range(0, 10, 2));
console.log(range(10, 30, 5));
console.log(range(-5, 2, 3));

"arguments" keyword in JavaScript

const add = (x=5, y=10) => console.log(x+y);
After we run the transpiler on this code, here is what the output would look like:
"use strict";
var add = function add() {
var x = arguments.length <= 0 || arguments[0] === undefined ?
5 : arguments[0];
var y = arguments.length <= 1 || arguments[1] === undefined ?
10 : arguments[1];
return console.log(x + y);
};
I got this snippet from Learning react book.
I have two question here
Can arguments.length be negative?
Does checking the second "||" condition be sufficient to check whether arguments[0] or arguments[1] is undefined?
Can arguments.length be negative?
No. How could you call a function and put a negative number of things between ( and )?!
Does checking the second condition be sufficient?
No. The function might be called with only one argument.

If then logic with && ||

Can someone explain to me or point me to documentation as to why the following function doesn't work?
var x = 1;
var y = 2;
var z = 1;
function logicTest() {
if ((x && y && z) === 1) {
return true;
} else {
return false;
}
}
console.log(logicTest())
I know that I can type it out the long way as follows:
var x = 1;
var y = 2;
var z = 1;
function logicTest() {
if (x === 1 && y === 1 && z === 1) {
return true;
} else {
return false;
}
}
console.log(logicTest())
But I'm really trying to understand why the first doesn't work and also if there is a better way of typing the second if/then statement or if that is just the way it will always have to be.
Thanks!
The expression
((x && y && z) === 1)
first involves the evaluation of (x && y && z). To evaluate that, JavaScript tests, in sequence, the values of x, y, and z. If, left to right, one of those values when coerced to boolean is false, evaluation stops with that (uncoerced) value as the value of the whole thing. Otherwise, the value of that subexpression will be the value of z, because it's the last subexpression in the && sequence.
In this case, x, y, and z are all non-zero numbers, so the overall result will be 1, because z is 1.
What you seem to want to be able to do is test whether all of a set of subexpressions are equal to the same value. That, as you've found, can only be determined by explicit comparison. It's also something that could be done by creating a list and then using array functions to perform the tests, which would be useful when there are more than just three subexpressions to test.
Also, on a stylistic note:
function logicTest() {
if (x === 1 && y === 1 && z === 1) {
return true;
} else {
return false;
}
}
Performing tests with relational operators like === generates boolean values. It's more concise to take advantage of that:
function logicTest() {
return x === 1 && y === 1 && z === 1;
}

Difference between two statements that declare an object

What is the difference between this statement
var X = X || {};
And this. They do the same thing? There is a performance difference?
var X = typeof X === "undefined" ? {} : X;
They're not the same.
The || will return the object when X is any possible falsy value.
The typeof check will only return {} if is X is undefined.
According to this test, the undefined check is nearly twice as fast. That's probably because no type casting is required.
In this case: var X = X || {} the X variable will be redefined if it's been declared but is falsy. So var X = 0; X = X || {}; would overwrite the 0 with an object.

Categories