relational comparison in JavaScript - javascript

I am confuse for these comparison and I don't know how can be happen.
in bottom code when I compare x and y for less than or great than, it return false but when I compare them with equals they return true!
do you know why this happen?
var x = { y: 10 };
var y = { y: 11 };
x < y; // false
x == y; // false
x > y; // false
x <= y; // true
x >= y; // true

now I understand how are x <= y and y <= x resulting in true however x < y and x == y and x > y are all false.
in continue of accepted answer I can say these happen because the spec says for x <= y , it will actually evaluate y < x first, and then negate that result. Since y < x is also false, the result of x <= y is true.

x < y; // false
x > y; // false
When any operand of a relational operator is an object, it is converted to a primitive value. So in this case, both x and y are first converted to primitive values and then compared with each other.
Both x and y will be converted to primitive values by eventually calling .toString() method on each object which will return a string of the form: [object Object] and since both objects will be converted in this string form, x < y and x > y both evaluate to false because both strings, i.e. [object Object] are equal.
x == y; // false
This evaluates to false because when types of both operands of == operator are same, javascript performs strict equality comparison ===, and as both objects are two separate objects in memory, they are not equal.
x <= y; // true
x >= y; // true
These both expressions evaluate to true because the following comparison
"[object Object]" == "[object Object]"
evaluates to true.

Related

const reversed = (x) => { if (x < 0) { return -1 * reversed(-x); } doesn't this recursive function make in infinite loop?

as x is constant so it is positive or negative.
because we are checking the value of x which is constant, so it doesn't matter if we put a negative sign before it.
so it will cause an infinity loop as x is still positive.
I'm going to rewrite your code for better readability.
const reversed = (x) => {
if (x < 0) {
return -1 * reversed(-x);
}
}
If we call reversed with x >= 0, then reversed returns undefined because of an implicit return in the JS function.
e.g. reversed(1) // --> undefined
If x < 0, then we return -1 * reversed(-x). x < 0 -> -x > 0.
We already know that reversed called with x >= 0 is undefined, so we get -1 * undefined which results in NaN (Not a Number).
TLDR:
x >= 0 -> reversed(x) -> undefined
x < 0 -> reversed(x) -> NaN

Trying to understand ternary condition logic in this example

I was doing a code kata which involves taking an array of football scores e.g.
["3:1", "2:2"] (Total points here would be 4, 3 + 1)
and applying some rules and then summing up the points. One of the solutions was:
const points = g => g.reduce((a, [x, _, y]) => a + (x > y ? 3 : x == y), 0)
To clarify, the rules are, if 1st value is greater than 2nd return 3, if equal return 1, else return 0, similar to a football match scoring system.
How does the part "x == y" work in this case, the rule here is that if "x == y" then a single point should be returned.
If someone can explain this in a simple way with an example, that would help me, thanks.
On a side note if someone can explain the "[x, _, y]" I would also appreciate that. I understand it's supposed to represent the current item in the array, but the current item is a string, not an array, so what is happening here?
This comes down to how JavaScript interprets true and false. Try in the console the following:
let x = 1;
let y = 2;
2 + (x == y);
What do we expect here? x == y is evaluated to false so that last line is really:
2 + (false);
Then to resolve the addition it coerces that false into a number. In JavaScript false is 0. So its actually:
2 + 0
Now try this:
let x = 1;
let y = 1;
2 + (x == y);
And what do we expect now? Since x == y will now evaluate to true and true will be coerced into a 1 this is actually:
2 + 1;
It is destructuring the string
x is the first char, _ is an unused variable and y is the 3rd;
const [x, _, y] = "3:1";
console.log(x);
console.log(_);
console.log(y);
It's just a quirky type coercion side-effect of JavaScript.
true can be coerced to 1 when used like this in an arithmetic operation:
console.log('hi' == 'hi'); // true
console.log(0 + (true)); // 1
console.log(0 + ('hi' == 'hi')); // 1
Here is a node session for you to study. First it shows modern JS string-to-array destructuring, second it shows some boolean behavior.
micha#linux-micha: ~
$ node
> [...arr] = "hello";
'hello'
> [...arr]
[ 'h', 'e', 'l', 'l', 'o' ]
> [x, dummy, y] = "3:2"
'3:2'
> x
'3'
> y
'2'
> dummy
':'
> typeof (x == y)
'boolean'
> typeof true
'boolean'
> typeof false
'boolean'
> 1 + true
2
> 1 + false
1
>
As you can see from that node session, "2:2" undergoes string-to-array destructuring, which results in x=2, y=2. Hence,x==y is boolean true. Now, there's a + (... x==y) in the function body, so the true value (aka x==y) is converted to a numerical 1 value, due to the + (plus) operator. So, a single point is returned.
Regards, M.
The String values are kind of arrays (iterables) with indexes, so you can access the indexes:
So, you can destructure strings.
console.log("3:1"[0]);
console.log("3:1"[1]);
console.log("3:1"[2]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
In your case, this is getting the first, second and third index [x, _, y]
let [x, _, y] = "3:1";
console.log(x, _, y);
This a + (x == y) is called coercion, true -> 1 and false -> 0.
console.log(1 + false);
console.log(1 + true);

Can someone explain what this JS snippet is doing?

Can someone please tell me what this snippet is doing?
Is it setting x to true if y is undefined?
var x = false;
var y = x === true;
The code
var x = false;
var y = x === true;
console.log(y);
is simply checking the condition x === true, like other programming language it will result to either true or false. Since you have var x = false; the condition x === true will result in false as false === true is always false. Now, the result of this condition is being assigned to the new variable y as var y = x === true; so the value for y will be false.
Set x to false
Is x exactly-equal to true?
2.1. If so, then set y to true
2.2. Otherwise, set y to false
There is no invokation of of global.undefined in this fragment.
The first line should be pretty clear, it sets x to false. The second line is a bit more difficult, first, it compares x to true. If x is exactly equal to true, it will set y to true. Since x is false, the comparison will also return false, so y will be set to false.
TL;DR, this is a convoluted way of setting y to false.
=== is a strict comparison operator. The value of variable y will only true if x is boolean and true, y will be false otherwise. Check this snippet out for example:
let a = 1;
console.log(a == true); // print true
let b = 1;
console.log(b === true); // print false, because `b` is a number, not boolean
let c = true;
console.log(c == true); // print true
let d = true;
console.log(d === true); // print true, because `d` is a boolean and its value is `true`
This var y = x === true; statement means: keep the returned value of (x === true) in the y variable. In your case, y will hold false as its value since x is a boolean, but its value is false.
Strict Equality Operator, === has a greater precedence over Assignment Operator, =. Therefore the check for x is done before assigning its value to y.
You can break this down into three statements.
var x = false
var tmp = (x === true)
var y = tmp
Since x is false, y will also get set to false.

When does a !== a? [duplicate]

Is there any value for what x === x returns false without NaN?
For example:
> x = 1
1
> x === x
true
> x = {}
{}
> x === x
true
> x = new Date()
Wed Nov 13 2013 15:44:22 GMT+0200 (EET)
> x === x
true
> x = NaN
NaN
> x === x
false
I see that the only value where x === x returns false is when isNaN(x) === true.
Is there another value of x for what x === x returns false? An official reference would be welcome!
The strict comparison between two equal non-NaN values will always be true (SLaks's answer correctly quotes the spec). However, it's possible for the expression x to change its value during the evaluation of the the equality. This can happen with property access when using accessor property descriptors (i.e., property getters):
foo = {};
Object.defineProperty(foo, "bar", {
get: function() {
return Math.random();
}
})
foo.bar === foo.bar; // false
If you do this for the global object window (or global in Node), then you can see the x === x comparison fail for a global-scope variable:
Object.defineProperty(window, "bar", {
get: function() {
return Math.random();
}
})
bar === bar; // false
The spec lists the exact rules for strict equality.
There are no other such cases, unless you count +0 and -0.
The SameValue algorithm (used for validating changes to read-only defined properties) has no such exceptions.

Is there any `x` value where Math.pow(x, 0) is NOT 1?

I found in a previous question that Math.pow(0, 0) === 1 returns true.
In the documentation we find the following rules for x^y:
If y is NaN, the result is NaN.
If y is +0, the result is 1, even if x is NaN.
If y is −0, the result is 1, even if x is NaN.
If x is NaN and y is nonzero, the result is NaN.
If abs(x)>1 and y is +∞, the result is +∞.
If abs(x)>1 and y is −∞, the result is +0.
If abs(x)==1 and y is +∞, the result is NaN.
If abs(x)==1 and y is −∞, the result is NaN.
If abs(x)<1 and y is +∞, the result is +0.
If abs(x)<1 and y is −∞, the result is +∞.
If x is +∞ and y>0, the result is +∞.
If x is +∞ and y<0, the result is +0.
If x is −∞ and y>0 and y is an odd integer, the result is −∞.
If x is −∞ and y>0 and y is not an odd integer, the result is +∞.
If x is −∞ and y<0 and y is an odd integer, the result is −0.
If x is −∞ and y<0 and y is not an odd integer, the result is +0.
If x is +0 and y>0, the result is +0.
If x is +0 and y<0, the result is +∞.
If x is −0 and y>0 and y is an odd integer, the result is −0.
If x is −0 and y>0 and y is not an odd integer, the result is +0.
If x is −0 and y<0 and y is an odd integer, the result is −∞.
If x is −0 and y<0 and y is not an odd integer, the result is +∞.
If x<0 and x is finite and y is finite and y is not an integer, the result is NaN.
What is interesting is that for any value of x the returned value is 1. Can we find any value for x for what Math.pow(x, 0) returns a value that is NOT 1?
I tried the following in the NodeJS shell, but I guess it's the same result in the browser console:
> Math.pow(undefined, 0)
1
> Math.pow(Date(), 0)
1
> Math.pow("asd", 0)
1
> Math.pow(function () {}, 0)
1
> Math.pow(function () { return 3}, 0)
1
> Math.pow([], 0)
1
> Math.pow(null, 0)
1
Maybe we find a JS trick that does this, like in the x === x // false (where isNaN(x) === false) case.
Just to clarify: y will be always 0. Only x is changing.
Your copy/paste from the documentation includes the requirement:
If y is +0, the result is 1, even if x is NaN
So it would seem the answer to your question is "No"
No, there is never any situation where the result will not be run. The definition of the function states that:
If y is NaN, the result is NaN.
If y is +0, the result is 1, even if x is NaN.
If y is -0, the result is 1, even if x is NaN.
All arguments are coerced to numeric type before being run, so therefore no matter what it will be 1. If multiple results are applicable, the first one in order that is applicable is the result returned, which in this case is 1.
As you have said that y is 0, it is therefore not NaN, and will not return NaN as a result.
ES5 §15.8.2:
Each of the following Math object functions applies the ToNumber abstract operator to each of its arguments (in left-to-right order if there is more than one) and then performs a computation on the resulting Number value(s).
Any arguments which aren't numbers (or strings that satisfy the format of a number) will be either coerced to 0 (for null, false and ""), 1 (for true) or NaN (anything else).
Right, since you are using node.js, which runs V8, lets have a look at the sources.
Function Math.pow is defined in math.js and states:
function MathPow(x, y) {
return %_MathPow(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y));
}
Macros TO_NUMBER_INLINE is used to cast any type to numeric value. Hence in the _MathPow operation we have numbers as arguments.
Lets move forward to hydrogen.cc, which has implementation of MathPow call that refers to HPower instruction in hydrogen-instructions.cc. The latter calculates the power using power_helper(c_left->DoubleValue(), c_right->DoubleValue()): the method defined in assembler.cc. Here we finally have the logic of the calculations:
double power_helper(double x, double y) {
int y_int = static_cast<int>(y);
if (y == y_int) {
return power_double_int(x, y_int); // Returns 1 if exponent is 0.
}
// ...
}
The comment (copied from the sources) says everything, and there is even no need to inspect power_double_int defined in the same file to say that every value passed to Math.pow as the first argument with y == 0 will return 1.
To say that definitely lets check power_double_int:
double power_double_int(double x, int y) {
double m = (y < 0) ? 1 / x : x;
unsigned n = (y < 0) ? -y : y;
double p = 1;
while (n != 0) {
if ((n & 1) != 0) p *= m;
m *= m;
if ((n & 2) != 0) p *= m;
m *= m;
n >>= 2;
}
return p;
}
From the above, n will always be 0, so while loop will never run, returning p = 1 unchanged.
The first three steps of the algorithm according to the ES5 spec are as follows:
If y is NaN, the result is NaN.
If y is +0, the result is 1, even if x is NaN.
If y is −0, the result is 1, even if x is NaN.
If you were writing an implementation of the ES5 standard, your code would probably look something like this:
function pow(x, y) {
if (isNaN(y)) return NaN;
if (y === 0) return 1;
// ... follow the other rules
}
There is not going to be any value of x that will cause it to return anything other than 1 when y === 0.

Categories

Resources