In MDN polyfill function for Array.prototype.includes(), I found the following code.
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
In the above code
typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y) this makes me confusing. If the typeof the variable is a number , isNaN will be always false right? so when this whole condition will return true? Can someone explain or did I understand it wrongly?
In JavaScript, the type of NaN is number. I guess this is because it is the result of mathematical operations.
See this question for more information.
This code will return true if the 2 elements are NaN, but false if the both are not numbers.
As you can see, the 1st example returns true is both isNaN() regardless of their type - which makes a equal b. The 2nd checks if both are numbers before using isNaN():
const checkEq1 = (x, y) => isNaN(x) && isNaN(y)
console.log(checkEq1(NaN, NaN)); // true
console.log(checkEq1('a', 'b')); // true - error
const checkEq2 = (x, y) => typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)
console.log(checkEq2(NaN, NaN)); // true
console.log(checkEq2('a', 'b')); // false
Nope, if typeof x === 'number', x can be NaN, and then isNaN(x) && typeof x === 'number' will both be true.
No idea why that function just doesn't use Number.isNaN(x) && Number.isNaN(y) though, since that will explicitly check if the value is NaN (as opposed to anything that can be NaN when converted to a number, as with isNaN).
Related
can someone explain this comparison statement ?
I understand how to compare with && and || but the one liner below does something else
typeof(varName) === 'undefined' == 0
Lets say that varName is undefined. Your line of code goes through these steps (each new line is the next step):
typeof(varName) === 'undefined' == 0
typeof(undefined) === 'undefined' == 0
'undefined' === 'undefined' == 0
true == 0
false
Now lets say that varName is defined as equal to 5:
typeof(varName) === 'undefined' == 0
typeof(5) === 'undefined' == 0
'number' === 'undefined' == 0
false == 0
true
This is bad code. You can get the same result with typeof(varName) !== 'undefined'
typeof(varName) === 'undefined' == 0
The above expression can also be written as
!(typeof(varName) === 'undefined')
Instead of using Not operator (!) they have used == 0. But if you do ===0, it will not work because it will also check for datatype and will always return false.
example :
true == 0 => false
false == 0 => true
But if you use ===
true === 0 => false
false === 0 => false
Note: typeof(varName) === 'undefined' == 0 is a bad way to do it.
Use not operator:
!(typeof(varName) === 'undefined')
From a bug report, I think that the following expression might throw an exception if x is null:
if ( !x || doSomething( x[prop], y[prop] ) === false )
The exception is:
Cannot read property 'prop' of null
... as if the right side of the || is evaluated even if the left side is true.
The javascript reference seems to indicate that that should not happen, but I'm not sure. I've tested that just writing x = null does not (always) crash, but is it guaranteed on every JS engine ?
EDIT:
Same question about
if( x && foo( x[prop] ) === true && bar() === false )
One way to put it is, does :
if( a && b && c )
... evaluates b or c if a === false ? The doc is not clear about that case, only for "a && ( expr1 && expr2 )", not "a && expr1 && expr2"
Full code snippet
var x = null;
var y = {
"p1": "p1",
"p2": "p2"
};
function f() {
return true;
}
for (var propName in y) {
if (x && f(y[propName]) === true && f(y[propName]) === false) {
doSomething(x[propName], y[propName]);
} else if (!x || f(x[propName], y[propName]) === false) {
console.log(y[propName]);
}
}
EDIT2: for completeness, the real (minimized) code that run in the browser
function a(c, b, e, f) {
for (var d in b) {
if (c && _.isObject(b[d]) === true && _.isArray(b[d]) === false) {
a(c[d], b[d], e, d + ".")
} else {
if (!c || _.isEqual(c[d], b[d]) === false) {
e.push({
name: f + d,
value: b[d]
})
}
}
}
return e
}
The Javascript || operator is short-circuiting. The right-hand side will not evaluate if the left-hand side is true. That's a fundamental property of the operator and should be equally implemented across all engines.
Therefore, the right-hand side will only evaluate if x is truthy, and all truthy values in Javascript should be subscriptable without error.
Having said that, y is completely unknown in this example and might throw an error.
"Is it guaranteed on every JS engine?"
We can't actually know that for sure, but the standard defines, how these operators should be implemented.
Logical OR:
Let lref be the result of evaluating LogicalORExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is true, return lval.
Let rref be the result of evaluating LogicalANDExpression.
Return GetValue(rref).
http://es5.github.io/#x11.11
Item 3 doesn't leave any room to doubts, lval is returned immediately if lref can be evaluated to truthy, and rref will never be evaluated.
if (typeof y != 'undefined' && typeof x != 'undefined' && x !== null && y !== null) {
if (doSomething( x[prop], y[prop] ) === false) {
//do stuff
}
}
do the safety check before. this should be working
but note:
if your prop Attribute does not exist, this will return an error too!
greetings
If I compare "a" and "b", that should be false.
If I compare "a" and "a", that should be true.
If I compare "" and null, that should be true.
I could write my own method, but thought there was perhaps a JavaScript shortcut.
Edit: I was thinking something like this:
areDbSame(s1, s2) {
if (s1 === null) s1 = "";
if (s2 === null) s2 = "";
return s1 === s2;
}
Edit2: Settled on this version:
areDbSame(s1, s2) {
return (s1 === null ? "" : s1) === (s2 === null ? "" : s2);
}
Just before you test the equality of your string, you could do a simple one line enforcement, by converting to '' in the case of null. For example (if you also don't care about undefined, false, etc):
// testString becomes the one you are testing
var testString = myString || '';
If you only want to ensure null is blank
var testString = (myString === null) ? '' : myString;
Then you can simply do your string comparisons using testString, and not worry about the null equalities.
IMO this is the cleanest answer because it doesn't convolute the original equality testing of javascript strings. It is the same as saying, let's split the problem up into two parts.
1) When should my string be considered blank, and
2) Now I can just check for regular string equality.
function areEqualStrings(a, b) {
var otherEqualValues = ['', null];
if(typeof a === 'string' && typeof b === 'string') {
return a === b;
} else if(otherEqualValues.indexOf(a) > -1 && otherEqualValues.indexOf(b) > -1) {
return !a === !b;
} else {
return false;
}
}
When coercing JavaScript values, !null is true and !'' is true, so those would result in being equal.
Here's the test (screenshotted from my console):
This function should do it. It type checks first and short circuits otherwise.
function stringCompare(a, b) {
if (((a === null || typeof a === 'string') ||
(b === null || typeof b === 'string')) &&
((a === '' && b === null) ||
(b === '' && a === null) ||
(a === b))) {
return true;
}
return false;
}
No it hasn`t. The two first cases you can do naturally using operator =.
The third case it is impossible because "" is considered a empty string and null has any type. So they never can be true naturally. To do this, you have to write your own method.
Just to be clear. You can use operators = (equal) to do comparison:
== equal to
`x == 8 false
x == 5 true
x == "5" true
=== equal value and equal type
x === 5 true
x === "5" false
Hope it helps
Should I use !== or ==!? Both work, but what is the standard?
I enter "else" for both cases:
var x;
if (x !== undefined)
{
alert("if..");
}
else
{
alert('else..') // <--- here
}
var y;
if (y ==! undefined)
{
alert("if..");
}
else
{
alert('else..') // <--- here
}
==! is not a comparison operator in Javascript. When you write foo ==! bar, you are actually writing foo == !bar, using the unary ! negation operator and the binary == comparison operator. This probably does not do what you want it to:
> 'b' ==! 'a'
false
> 'b' !== 'a'
true
This happens to "work" in the particular situation you describe because !undefined evaluates to true, and y == true for undefined y is false, thus putting you on the else branch.
if (x !== undefined)
checks if x is not undefined, while
if (y ==! undefined)
negates undefiend (which returns !undefined == true) and then checks it for equality with y
This code is from the section of recursion.
var getElementsByAttribute = function (att, value) {
var results = [];
walk_the_DOM(document.body, function (node) {
var actual = node.nodeType === 1 && node.getAttribute(att);
if (typeof actual === 'string' &&
(actual === value || typeof value !== 'string')) {
results.push(node);
}
});
return results;
};
I don't understand the point of the clause below:
typeof actual === 'string' && (actual === value || typeof value !== 'string')
How is it different from?
typeof actual === 'string' && actual === value
typeof actual === 'string' && (actual === value || typeof value !== 'string')
This will return true if and only if actual is a string, and either actual === value, or value is not a string.
typeof actual === 'string' && actual === value
This will return true if and only if actual is a string and either actual === value.
In other words, the first condition returns true if value is anything other than a string, whereas the second condition will only return true if it is a string, and strictly equal to actual.