why the inconsistency performance in these two expressions? - javascript

''.valueOf()// an empty string
false.valueOf()// false
but why
+'' // 0
+false // 0
I read the tutorial, the algorithm of numeric conversion is:
If valueOf method exists and returns a primitive, then return it.
Otherwise, if toString method exists and returns a primitive, then return it.
Otherwise, throw an exception.
This is conflict with the real case, if that is the rule, then I think both ''.valueOf() and false.valueOf() should return 0. Could anyone please let me know the possible reason?

From the Object.prototype.valueOf() MDN page:
The valueOf() method returns the primitive value of the specified object.
Since you're calling valueOf() on primitives, it simply returns those primitives.
(In JavaScript, there are 6 primitive data types: String, Number, Boolean, Null, undefined, Symbol (ES6))
Now, from the Unary Plus (+) MDN page:
The unary plus operator precedes its operand and evaluates to its operand but attempts to converts it into a number, if it isn't already.
Basically, +value is equivalent to calling Number(value).
Both Number('') and Number(false) return 0.

.valueOf is returning a primitive - the empty string. false is also a primitive.
The + operator is shorthand for converting a variable to a number. In this case, it is converting the false-y values to 0 - no conflict at all.

Related

Why does Number(null) return 0, and parseFloat(null) return NaN?

I'm trying to write a helper function that will cast a String coming from an <input type="text" /> to a Number.
As I wasn't sure whether to use parseFloat(str) or Number(str) I doublechecked how they handle potentially problematic arguments.
See:
console.log(Number(null)); // 0
console.log(parseFloat(null)); // NaN
console.log(parseInt(null)); // NaN
console.log(isNaN(null)); // false
Both parseFloat and parseInt return NaN, whereas Number returns 0. Number seems more coherent here with isNaN(null).
Why is that?
Number constructor tries to coerce the argument to number. So empty string '', false, null and all falsy values become 0.
Similarly, Number(true) will return 1. Number('some string') will be NaN as 'some string' cannot be converted to a number.
Note that as pointed out in the comments, Number(undefined) is NaN and not 0 in arithmetic operations. (Read here https://codeburst.io/understanding-null-undefined-and-nan-b603cb74b44c)
Read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
parseInt/Float convert their argument to a string, read it char by char from the left and try to make a number from what they've found. Since String(null) is "null" and a decimal number cannot start with "n", parseInt(null) will be NaN. If you provide a different base, where n, u and l are digits, the result will be different:
console.log(parseInt(null, 32))
Number converts its argument as a whole into a number. Number(null) returns +0 because the ECMA committee wants it to: http://www.ecma-international.org/ecma-262/7.0/#sec-tonumber . This is probably for historical reasons.
global isNaN (not to confuse with Number.isNaN) applies Number to its argument and returns true if the result is NaN. Since Number(null) is +0, isNaN(null) is false.
Hope this sheds some light...
NaN stands for "Not a Number". ParseFloat and ParseInt return real numbers and integers, so this is like an error returned by the function. Number(), on the other hand, represents the object's value. For instance, Number(false) will output 0.
The reason seems to be quite subtle with how parseInt and parseFloat work:
If the argument passed to parseInt/parseFloat is not a String (which null isn't), then it calls toString(null) which returns "[object Undefined]".
If the first character cannot be converted to a number, parseInt returns NaN.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

Can someone explain to me why this code returns 1

Why this code returns 1, the method toString even not called anywhere, + operator should turn its operand to a number but i tried this and returned NaN
+{} // NaN
+{a: 2} //NaN
so why this code returns 1 ????
+({x:+null , y : +'001' , toString : function(){return this.x+this.y;}})
+({x:+null , y : +'001' , toString : function(){return this.x+this.y;}})
You are overloading toString which function returns (+null+'001')
+null coerces null to 0;
+'001' coerces the string to 1
you are returning 1 from toString.
In the previous cases, the result of non a overloaded toString method of an object literal is "[object Object]" which coerced to a number gives NaN.
The only thing that matters here is what toString, overloaded or not, returns.
When an expression uses a non-number value in a way that needs it to be a number, the value is first converted to its primitive value equivalent. Then, the primitive value is coerced to a number.
The steps taken by a JavaScript interpreter are as follows:
Call valueOf and convert it to a number, if possible.
Call toString, and if the return value is primitive, convert it to a number, if possible.
Throw TypeError.
In your case, since you use the unary + operator with a non-number object, and the unary + operator is only defined for numbers, these steps are taken. Your object does not have a valueOf, but it does have a toString method, so the return vaule of toString, coerced to a number, is used to evaluate the expression.
Kyle Simpson's excellent You Don't Know JS: Types & Grammar has more on type coercion, if you would like to explore further.

EloquentJavaScript: !Number.isNaN() what is the purpose? [duplicate]

Soooooo isNaN is apparently broken in JavaScript, with things like:
isNaN('')
isNaN(' ')
isNaN(true)
isNaN(false)
isNaN([0])
Returning false, when they appear to all be... Not a Number...
In ECMAScript 6, the draft includes a new Number.isNaN but it looks like (imo) that this is also broken...
I would expect
Number.isNaN('RAWRRR')
To return true, since it's a string, and cannot be converted to a number... However...
It seems that things that I would consider... not a number, are indeed, not, not a number...
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-isfinite-number
The examples on MDN say:
Number.isNaN("blabla"); // e.g. this would have been true with isNaN
I don't understand how this is "More robust version of the original global isNaN." when I cannot check to see if things are not a number.
This would mean we're still subjected to doing actual type checking as well as checking isNaN... which seems silly...
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-isnan-number
The ES3 draft here basically says, everything is always false, except with its Number.NaN
Does anyone else find this is broken or am I just not understanding the point of isNaN?
isNaN() and Number.isNaN() both test if a value is (or, in the case of isNaN(), can be converted to a number-type value that represents) the NaN value. In other words, "NaN" does not simply mean "this value is not a number", it specifically means "this value is a numeric Not-a-Number value according to IEEE-754".
The reason all your tests above return false is because all of the given values can be converted to a numeric value that is not NaN:
Number('') // 0
Number(' ') // 0
Number(true) // 1
Number(false) // 0
Number([0]) // 0
The reason isNaN() is "broken" is because, ostensibly, type conversions aren't supposed to happen when testing values. That is the issue Number.isNaN() is designed to address. In particular, Number.isNaN() will only attempt to compare a value to NaN if the value is a number-type value. Any other type will return false, even if they are literally "not a number", because the type of the value NaN is number. See the respective MDN docs for isNaN() and Number.isNaN().
If you simply want to determine whether or not a value is of the number type, even if that value is NaN, use typeof instead:
typeof 'RAWRRR' === 'number' // false
No, the original isNaN is broken. You are not understanding the point of isNaN.
The purpose of both of these functions is to determine whether or not something has the value NaN. This is provided because something === NaN will always be false and therefore can't be used to test this.
(side note: something !== something is actually a reliable, although counter-intuitive, test for NaN)
The reason isNaN is broken is that it can return true in cases when a value is not actually NaN. This is because it first coerces the value to a number.
So
isNaN("hello")
is true, even though "hello" is not NaN.
If you want to check whether a value actually is a finite number, you can use:
Number.isFinite(value)
If you want to test whether a value is a finite number or a string representation of one, you can use:
Number.isFinite(value) || (Number.isFinite(Number(value)) && typeof value === 'string')
As mentioned in a comment isNaN() and Number.isNaN() both check that the value you pass in is not equal to the value NaN. The key here is that NaN is an actual value and not an evaluated result e.g. "blabla" is a String and the value is "blabla" which means it is not the value "NaN".
A plausible solution would be doing something like:
Number.isNaN(Number("blabla")); //returns true.
The key difference between the two is that the global isNaN(x) function performs a conversion of the parameter x to a number. So
isNaN("blabla") === true
because Number("blabla") results in NaN
There are two definitions of "not a number" here and that's perhaps where the confusion lies. Number.isNaN(x) only returns true for the IEEE 754 floating point specification's definition of Not a Number, for example:
Number.isNaN(Math.sqrt(-1))
as opposed to determining whether the object being passed in is of numeric type or not. Some ways of doing that are:
typeof x === "number"
x === +x
Object.prototype.toString.call(x) === "[object Number]"
Basically, window.isNaN performs a type conversion to a number, then checks if it is NaN. Whereas, Number.isNaN doesn't try to convert its argument to a number. So basically, you can think of window.isNaN, and Number.isNaN as working like so.
window.isNaN = function(n){
return Number(n) !== Number(n);
}
window.Number.isNaN = function(n){
return n !== n;
}
Please note that you don't need actually to use the window. to call isNaN or Number.isNaN. Rather, I am just using it to provide a better distinction between the two similarly-named methods to try to cut down on confusion.
~ Happy Coding!
The following works because NaN is the only value in javascript which is not equal to itself.
Number.isNaN = Number.isNaN || function(value) {
return value !== value;
}
Per, MDN, it (NaN) is the returned value when Math functions fail and as such it is a specific value. Perhaps a better name would have been, MathFunctionFailed.
To determine if something is a number requires parsing which fails nicely over a broad range of non numeric inputs, successfully detecting numbers and strings representing numbers, hence:
function isNumber(v) {return Number.isNaN(parseFloat(v)); }
1. Number.isNaN
alert(Number.isNaN('Hello')); // false
Shouldn't it return true because Hello is a string and its Not A Number right ? But Lets know why it returns false.
MDN docs says :
true if the given value is NaN and its type is Number; otherwise,
false.
Yes Hello value is NaN but the type is string , you can check the type as follows:
alert(typeof `Hello`); // string
Usage:
Use when you want to check the value is both NaN and type is number.
2. isNaN
alert(isNaN('Hello')); // true
MDN docs says:
true if the given value is NaN; otherwise, false.
Usage:
Use when you want to check value is just NaN.
3. jQuery.isNumeric()
Jquery Docs Says :
Determines whether its argument represents a JavaScript number.
alert($.isNumeric('Hello')); // false
alert($.isNumeric(3)); //true
Usage:
Use when you want to check value is a number or can be converted to a number.
Reference
I use a simple workaround to check Number.isNaN():
let value = 'test';
Number.isNaN(-value); // true
value = 42;
Number.isNaN(-value); // false
js trying to convert the value to the negative Number, if the conversion is failed - we have NaN.
Simple, isn't it?
Moreover, online benchmark tests say Number.isNaN is lighter than isNaN.
Number.isNaN(x) checks if x is directly evaluated to NaN or not.
RAWR is not the same as NaN. Think of NaN as an entity to represent the result of some mathematical calculation where the computer does not know how to represent the number.
A mathematical operation is not going to yield a non-numeric result, hence the typeof NaN is number.
The string RAWR had undergone no mathematical operation to yield NaN. However, if you were to call Number.isNaN(+'RAWR'), it would result in NaN since the unary + operator is trying to convert 'RAWR' to a number.
On the other hand, isNaN(y) tells whether y can be converted to a number or not. If isNaN(y) is false, y can be converted to a number. But if isNaN(y) is true, y can not be converted to a number.
So a good rule of thumb is:
Do I want to check if x can be successfully converted to a number? Use isNaN(x) == false in that case. Unsuccessful conversion results in NaN.
Do I want to check if x is evaluated to NaN? Use Number.isNaN(x) == true for that.
#phill, as stated in other responses, neither is broken.
Number.isNaN work on a number or instance of Number, so even Number.isNaN(new Date(NaN)) is false.
isNaN, on the other hand, is generic and tries to convert its parameter to a number before checking it.
If you want to determine if a value is (or contains) NaN, you can use this function:
function valueIsNaN(value) {
// eslint-disable-next-line no-self-compare
return value !== value || typeof value == 'object' && Number.isNaN(value.valueOf());
}

What is the domain of the plus operator in JavaScript?

I'm looking at the MDN documentation of the plus (a + b) operator in JavaScript. It seems like the operator is defined on all combinations of number, string, and bool arguments. From experimentation, it is also defined on arrays, objects, null, closures ...
The question: is there any combination of values for which the plus operator is not defined, i.e. those arguments are not in the domain of the + function? (Where operationally, "not defined" basically means an exception will be thrown or the program will halt with an error if + is applied to those arguments.)
Bonus points for answering the equivalent question for the other "arithmetic operators" (which seem to do far more than arithmetic ...).
The + operator is only defined for numbers (addition) and strings (concatenation).
However, it coerces its arguments to number or string. Full details in the spec, §11.6.1. Basically: Processing + does a "to primitive" on the operands, which means it then ends up with numbers, strings, booleans, nulls, or undefineds. If either operand, after coercion to primitive, is a string, it then coerces the other to string and does concatenation; otherwise, it coerces both to number and does addition.
The result of "to primitive" on objects depends on the object, but most objects end up coercing to string or number.
The only objects that can't be coerced to primitives are objects lacking both a toString and a valueOf*; in that case, §8.12.8 tells us that a TypeError is thrown. In practice, the only objects that won't have toString and valueOf are ones that A) Don't have their own copy of them, and B) Have no prototype or a prototype chain that doesn't include Object.prototype. For example, an object created by Object.create(null) (which has no prototype).
So no, there's no combination of values for which + is undefined but there is an edge case where it will throw a TypeError:
(Normal case) Both operands can coerced to a primitive, and any primitive can be coerced to a string or a number (the resulting number may, of course, be NaN), and so we get a resulting value, or
(Edge case) One of the two operands can't be converted to primitive, in which case we get a TypeError
* Okay, they don't have to be missing: If the object has toString but toString returns a non-primitive, then we get the TypeError if the object doesn't have valueOf or the object has valueOf, but valueOf also returns a non-primitive. In practice, toString and valueOf are supposed to return primitives.

How does JavaScript evaluate if statement expressions?

I always thought that JavaScript's if statements did some kind of casting magic to their arguments, but I'm a little wary of what's actually going on behind the scenes.
I recently found a JavaScript comparison table and noticed that even though -1 == true evaluates to false, if(-1){...} will execute.
So within JavaScripts if statements, what happens to the expression? It seems reasonable to assume that it uses !!{expression} to cast it to an inverse boolean, then invert it again, but if that's the case, how does JS decide whether an object's inverse boolean representation is truthy or not?
JavaScript is wonky.
Yes, -1 == true results in false, but that's not what the if statement is doing. It's checking to see if the statement is 'truthy', or converts to true. In JavaScript, that's the equivalent of !!-1, which does result in true (all numbers other than zero are truthy).
Why?!?
The spec defines the double equals operator to do the following when presented with a number and a boolean:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
ToNumber will convert the boolean true into the number 1, so you're comparing:
-1 == 1
which anyone can tell you is clearly false.
On the other hand, an if statement is calling ToBoolean, which considers any non-zero, non-NaN number to be true.
Any JavaScript developer really needs to look at the documentation -- for this case, located here: http://www.ecma-international.org/ecma-262/5.1/#sec-9.2
9.2 ToBoolean
The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:
Argument Type Result
Undefined false
Null false
Boolean The result equals the input argument (no conversion).
Number The result is false if the argument is +0, −0, or NaN; otherwise the result is true.
String The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
Object true
(Sorry about the formatting, can't make a table here.)
From JavaScript The Definitive Guide
The following values convert to, and therefore work like, false:
undefined
null
0
-0
NaN
"" // the empty string
All other values, including all objects (and arrays) convert to, and work like, true. false, and the six values that convert to it, are sometimes called falsy values, and all other values are called truthy.
These things by themselves are falsy (or evaluate to false):
undefined
null
0
'' or ""
false
NaN
Everything else i truthy.
Truthy-ness or falsy-ness is used when evaluating a condition where the outcome is expected to be either truthy (true) or falsy (false).
In your example if(-1 == true), you are comparing apples and oranges. The compare is evaluated first (and resulted in false), and the results of that is used in your condition. The concept of truthyness/falsyness isn't applied to the operands the comparison.
When if state using with comparing variable different type js use .toString и .valueOf ( for more information check http://javascript.info/tutorial/object-conversion ) - just keep this in mind - it make so example much more easy to understand

Categories

Resources