Why is there an isNaN() function in JavaScript whilst isUndefined() must be written as:
typeof(...) != "undefined"
Is there a point I don't see?
In my opinion its really ugly to write this instead of just isUndefined(testValue).
There is simply no need for an isUndefined() function. The reason behind this is explained in the ECMAScript specification:
(Note that the NaN value is produced by the program expression NaN.) In some implementations, external code might be able to detect a difference between various Not-a-Number values, but such behaviour is implementation-dependent; to ECMAScript code, all NaN values are indistinguishable from each other.
The isNaN() function acts as a way to detect whether something is NaN because equality operators do not work (as you'd expect, see below) on it. One NaN value is not equal to another NaN value:
NaN === NaN; // false
undefined on the other hand is different, and undefined values are distinguishable:
undefined === undefined; // true
If you're curious as to how the isNaN() function works, the ECMAScript specification also explains this for us too:
Let num be ToNumber(number).
ReturnIfAbrupt(num).
If num is NaN, return true.
Otherwise, return false.
A reliable way for ECMAScript code to test if a value X is a NaN is an expression of the form X !== X. The result will be true if and only if X is a NaN.
NaN !== NaN; // true
100 !== 100; // false
var foo = NaN;
foo !== foo; // true
The use case var === undefined works almost everywhere, except for the cases covered by this answer, where either undefined is assigned a value, or var is undefined.
The reason such a function cannot exist, is clear from the latter case. If var is undefined, then calling the supposed function isUndefined(var) will result in a ReferenceError. However introducting a new keyword, e.g. isundefined var could address this issue.
But despite being valid, both of the above cases are poor uses of javascript. This is the reason I believe such a keyword does not exist.
isUndefined could be written as
testValue === undefined
like for every other value.
This does not work with NaN however, as NaN !== NaN. Without the ability to use a comparison, there was need for an isNaN function to detect NaN values.
This isn't a direct answer to the question as others have already answered, it's more to highlight libraries that contain an isUndefined() function for anybody looking for quick solution and they're in a position to use them.
Underscore and Lo-dash both contain an isUndefined() function, the latter, because it's built upon Underscore.
http://underscorejs.org/#isUndefined
https://lodash.com/docs#isUndefined
Related
In the book 'Functional javascript' by Michael Fogus, I faced with one expression that I still can't undrestand.
Here is the function:
function defaults(d){
return function(o, k){
var val = fnull(_.identity, d[k]);
return o && val(o[k]);
}
}
where
function fnull(fun /*, defaults*/){
var defaults = _.rest(arguments);
return function(/* args */){
var args = _.map(arguments, function(e, i){
return existy(e)?e : defaults[i];
});
return fun.apply(null, args);
};
};
function existy(x){return x != null}
(underscore is the object of Underscore.js library)
and the example of use:
function doSomething(config){
var lookup = defaults({critical:108});
return lookup(config, 'critical');
}
doSomething({critical: 9});
//=> 9
doSomething({});
//=> 108
I've recreated exapmle in node.js and it works fine, but I wonder why is the logical 'and' in the return line of 'default' function?
return o && val(o[k]);
What is the point of doing that? I checked the exapmle with
return val(o[k]);
and it also worked well.
It's hard to believe that this is just a mistake...
The logical and will make sure the second part is only evaluated if the first part is true. If o does not evaluate to true, the expression returns false. Otherwise, it returns val(o[k]).
This is used as a quick check to see if o is not false / null / undefined.
return o && val(o[k])
mean that if "o" is TRUE it will return "val(o[k])"
given "expr1 && expr2":
Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
That is smart usage of something called short "short-circuiting" in logical expressions.
As logical expressions are evaluated left to right, they are tested
for possible "short-circuit" evaluation using the following rules:
false && (anything) is short-circuit evaluated to false.
true ||(anything) is short-circuit evaluated to true.
The rules of logic guarantee that these evaluations are always correct. Note that the (anything) part of the above expressions is not evaluated (meaning not ran at all), so any side effects of doing so do not take effect. There are also benefits to it.
Usage:
Make your expressions evaluate faster by putting something easily calculable or likely to be true/fail at leftmost position in expression.
For example parOfExpressionLikelyToBeTrue && (rest of expression) will in most cases not even calculate the other part of expression. Same goes for parOfExpressionLikelyToBeTrue || (rest of espression).
Same can be used if something is very time consuming to calculate, you push it as far back to the right in expression. For example (rest of the expression) && ThisCostsALotOfTime or (rest of the expression) || ThisCostsALotOfTime. Here when first parts of expression short-circuit you save time on your time consuming part.
Short circuit existence evaluation. Lets say you need to check if your object's property pr is 3? What would you do? obj.pr === 3? Yes and no. What if property is missing? It's fine you will get undefined and that is not === 3. But what if object is not there. You will get trying to read pr of undefined error. You can use short-circuit logic here to you benefit by being defensive and writing the expression as if (obj || obj.pr === 3). This ensures there are no errors, only true and false.
Short circuit initialization. Let's say you wanna say variable a is b. But b might be undefined. And you wanna your variable to have a default. You could write a=b and then check if a is undefined and set it to default or you can be clever and write it as a = b || 3. This way a is b or if be is undefined it's 3. Ofc, you can use this for late initialization as well a = a || 3.
Making sure object for function exists before trying to run function. Same as before mentioned with properties you might wanna test if object containing the function exists before running the function. Let's say you got object obj and function fn as it's property. You might call that function like obj.fn(). It's fine, but if obj is undefined you will get an error. Being defensive you might wanna write: obj && obj.fn().
Running the function only if there is one. Since functions in JS can be passed to other functions you can not be sure at run time it's there. Being defensive you might wanna run your function as (typeof passedFunction === "function" && passedFunction() instead just passedFunction() which my produce an error.
other smart things like guardian expressions etc which are complicated and too many to for me to remember all and you should avoid them anyway for better code readability.
How can I efficiently check in asm.js code whether a floating point value is a NaN?
A way that works in principle is to import the global isNaN JavaScript function as a foreign function into the asm.js module. As calling foreign function is expensive, though, so this won't yield optimal code.
Comparing to the value NaN (which is part of the standard library) is no option because the comparision of a NaN to another NaN always yields false by JavaScript semantics.
Examining bits on the heap is also no option because the endianess is not specified.
Why is isNaN not part of the standard library in asm.js?
This property of NaN is commonly used to identify it :
var isNaN = a!=a;
From Wikipedia :
The equality and inequality predicates are non-signaling so x = x
returning false can be used to test if x is a quiet NaN
if (value !== value) {
// Definitely NaN
}
You can make it as a function like this
function isNaN(inputValue) {
return inputValue !== inputValue;
}
Try it: In Node.js, or Firefox, open a REPL, and type:
Number.isNaN('asdf');
How can this not be NaN? What is NaN if not this?
You have a misconception here. The fact that NaN means Not a Number does not mean that anything that is not a number is a NaN.
NaN is a special value on floating point arithmethic that represents an undefined result of an operation. For example, 0 / 0 generally yields NaN as a result.
More information here and here.
There is no notion of Number.isNaN() in the language specification. The only specified function is the global isNaN (15.1.2.4), which will correctly return true on anything that isn't a number or cannot get correctly transformed into a number.
Number.isNaN (which returns true on NaN) is probably an implementation detail part of the next standard draft (see remyabel' answer) which could be used internally by isNaN.
Just a note, it seems that Number.IsNaN has limited support.
This output:
console.log(Number.isNaN("blabla"));
Gives false, and false !== NaN:
console.log(false !== NaN)
console.log(false !== Number.NaN);
Here's a reference:
When the Number.isNaN is called with one argument number, the
following steps are taken:
If Type(number) is not Number, return false.
If number is NaN, return true.
Otherwise, return false.
This function differs from the global isNaN function (18.2.3) is that
it does not convert its argument to a Number before determining
whether it is NaN.
I am l33t for I have 1337 reputation.
Try this:
function checkNaN(value)
{
return value !== value;
}
It works because (I believe) NaN is the only thing in JS that does not strictly equal itself.
This is part of the EcmaScript 6 Standard.
Number.isNaN returns whether a value is NaN without coercing the parameter.
Number.isNaN("xmfds"); // false
Number.isNaN("ose"); // false
isNaN returns whether the value is NaN after coercing the parameter to Number type.
isNaN("ose") -> isNaN( Number("ose") ) -> isNaN(NaN); // true
I have just run a very simple JavaScript performance test (don't ask why). The test declares a variable, but doesn't assign anything to it:
var x;
It then compares the speed of comparing the value variable to null, and to undefined, in other words:
var y = (x == null); and var y = (x == undefined);.
I was expecting the comparison with undefined to be the fasted. In fact it was nowhere near. The comparison with null was far and away the fastest, around 80% faster.
The results I've described above come from running the tests in Chrome (version 13). Running them in Firefox produces results far closer to what I would have expected (the comparison with undefined is faster than with null, albeit very marginally).
So, my question is what could the cause of this be? Why does Chrome seem to favour the comparison with null so greatly?
For quick reference, here's a screenshot of the results:
null is a reserved keyword which cannot be overriden, so when you are doing a comparison against null, all you have to do is a single comparison.
However, when you are checking against undefined, the engine must do a type lookup and then a comparison, meaning that it is actually slightly more demanding.
If you need to actually check to see if something is undefined, you should use
if(typeof notSet == "undefined"){ }
Proof
Try it... and set something to null in your JavaScript console.
null = "will error";
// Errors with --> ReferenceError: invalid assignment left-hand side
However, if you try and do it with undefined, it won't error. That is not to say that you can override undefined, because you can't, but that undefined is its own primitive type.
The only real similarity between null and undefined, is that they can both be coerced into a boolean false.
if i think well, they are not the same. so you can't use null instead of undefined.
typeof !== "undefined" vs. != null
You're comparing against the lookup of a variable called undefined (which returns an undefined value), so it's not doing what you were intending.
There are ways to check whether a variable is undefined. As the other posters have mentioned, typeof x === 'undefined' is one. (There's probably another possibility that is something like hasOwnProperty('x') executed on the global object, but that doesn't check the scope chain.)
I recently discovered that this:
if (typeof this._minLat === 'undefined') {
this._minLat = Math.min(...this.points.map(point => point.lat));
}
return this._minLat;
seems to be many times faster than this:
return this._minLat || Math.min(...this.points.map(point => point.lat));
I had an interesting interview question today that stumped me a little. I was asked about falsey values. So undefined, NaN, null, 0, and an empty string all evaluate to false. What is the reason this is useful to know in JavaScript? The only thing I can think of is instead of having to do this:
if (mystring === '' || mystring === undefined) { }
I can do this:
if (!mystring)
Is this the only useful application?
One dangerous issue of falsey values you have to be aware of is when checking the presence of a certain property.
Suppose you want to test for the availability of a new property; when this property can actually have a value of 0 or "", you can't simply check for its availability using
if (!someObject.someProperty)
/* incorrectly assume that someProperty is unavailable */
In this case, you must check for it being really present or not:
if (typeof someObject.someProperty == "undefined")
/* now it's really not available */
Also be aware that NaN isn't equal to anything, even not to itself (NaN != NaN).
There are two separate issues with 'falsey' values in JavaScript.
Firstly there is the official conversion scheme, which is what is returned by Boolean(x). This returns false when x is false or 0 or NaN or null or undefined or "" and true otherwise. This is the same behaviour as the
if (condition) {/*true path*/} else {/*false path*/}
that is, the false path is executed if Boolean(condition) would have returned false and the true path is executed otherwise. This behaviour is often used to check to see if a property is defined. However, doing that is not safe unless you are certain that the property would be an object or an array if it is defined. The safest way to test if a property is defined is to do
if (property != null) { /*property is defined*/}
which makes sure that the property is not null or undefined. If you only want to make sure the property is not undefined do
if (property !== undefined) { /*property is not undefined (but may be null)*/ }
(notice the extra = in !==).
Secondly, there are all the values that == false. This is everything that can be coerced to 0 (which is what false gets coerced to). This includes all the values that convert to false except NaN (which can't == false by virtue of it never == anything), null and undefined. But it also includes all objects that when converted to a string and then converted to a number are equal to 0. For example, this includes everything that when converted to a string is either the empty string "" or "0" or "-0" or "+0" or "0x00" or "000" or "0e0" or "0.0000"...., for example,
({toString: function() {return "-00.0e000";}}) == false
is true. Interestingly, this includes the empty array, and any nesting of arrays containing only a single other item that returns an empty or 0 string since arrays rendered as strings show only the contents without the surrounding brackets. That is,
[[[[0]]]] == false; // Because [[[[0]]]].toString() === "0"
[] == false;
[[[""]]] == false;
["0"] == false;
[[({toString: function() {return "0";}})]] == false;
The full algorithm for calculating == false is described here.
The reason this matters is because it can lead to subtle, difficult to find bugs if you don't understand most of these rules. Most important takeaways are probably how the if (condition) works and that using === avoids most of the other crazy stuff.
It's important to understand how this works in JS, so you're not surprised. Not necessarily just what is falsey, but what is truthy and how they compare to each other.
One example is that '0' is considered equal to 0 with ==, but it is not equal to '' - though 0 is. JavaScript comparison isn't always transitive.
So this means that just because (foo==bar && bar==fizz) is true, (foo==fizz) is not always true. To go with the above example, '0'==0, and 0=='', but '0'!='' - because you're comparing strings in the latter instance, so they are compared as strings and not coerced to numbers.
It is important to know that 0 evaluates to false to prevent doing things like:
if(str.indexOf('foo'))
It's useful to detect if a browser is has specific predefined objects:
if(!!navigator.geolocation){
// executes if the browser has geolocation support
}
if(!!document.createElement('canvas').getContext){
// executes if the browser supports <canvas>
}
Explanation: navigator.geolocation is an object or undefined. In the case it's an object !navigator.geolocation will return false, if it's undefined it'll return true. So, to check if a browser has geolocation enabled, you want to 'flip' the boolean once more, by adding another !.
They're also useful for setting default values...
function foo(bar){
alert(bar || "default");
}
I know a lot of people try to do
if (typeof(foo) === "undefined"){}
to get around falsiness, but that's got its own problems because
typeof(null) === "object"
for some reason