new Date('Sep 23, 2019') > 0 ----> true
new Date('Sep 23, 2019') > 's' ----> false
When date compared with primitive is greater or lower than primitive?
F.ex. I need to compare any date with a primitive which is lower than the date.
When Date is compared to Number, using one of the <, <=, > or >= operators, the Date is converted to milliseconds (as if .getTime() is invoked on it).
When Date is compared to String like "1569177000000", the string is converted to the number too.
When Date is compared to String like "s" that cannot be converted to a number, there is no ordering: you will always get false (any comparison to NaN is false).
See MDN:
For relational abstract comparisons (e.g., <=), the operands are first converted to primitives, then to the same type, before comparison.
Specifically, for >, see here in the specification, where LeftFirst is false.
It's pretty complicated, but both sides are converted to a primitive (preferably a number) if they aren't already. When this is done with a Date, it returns the date's Unix timestamp.
Because both sides are then numbers, it's straightforward after that - the interpreter just checks which number is larger.
You can use the valueOf function on date
// Convert date into primitive
new Date('Sep 23, 2019').valueOf() //1569177000000
you can use getTime() or date functions to convert date into primitive value and then use a comparison operator.
Related
Is there a primitive or data structure in javascript that will always return true when compared to a number? I.e.
theVariable > x //true
where x is any number of the integer type?
where x is any number of the integer type?
Integer is not a type in ECMAScript, so if that is a condition then you first need to test if x is an integer, so something like:
Number.isInteger(value) && Infinity > value;
will do the job.
The isInteger test is strict, so if value is a string like "2" it will fail. If strings should be allowed then convert to Number first, e.g.:
Number.isInteger(+value) && Infinity > value;
To use Number.isInteger, support for ECMAScript 2015 is required so IE is excused, MDN has a polyfill.
If you are just trying to test if value is a finite integer, then just:
Number.isInteger(value);
which returns false for Infinity and -Infinity and true for all integers in between (that can be represented in ECMAScript).
Why Javascript's Date object returns different value for implicit conversions?
Number conversion:
+new Date()
// returns 1456293356618 as expected
String conversion:
''+new Date()
// returns "Wed Feb 24 2016 09:26:28 GMT+0" but "1456293356618" as a string was expected
Where can I find the documentation on ECMAScript and the implementation on v8's source?
Edit: I'm not looking for the solution for the expected result. I want to find the documentation in the specs.
The + operator is overloaded. In:
+new Date()
it is treated as the unary + operator and coerces the value to Number. In:
'' + new Date() // note one value is a string
it is treated as the string concatenation operator and coerces the values to String. In:
5 + 6 // note both values are number
it is treated as the addition operator. Since the values are numbers, no coercion is necessary.
Note that whether + does addition or concatenation depends on the values and is described in ECMAScript 2015 §12.7.3.1 step 11.
I think you are refering to this Overview of Date Objects and Definitions of Abstract Operators, specifically Section 20.3.1.1
A Date object contains a Number indicating a particular instant in time to within a millisecond. Such a Number is called a time value. A time value may also be NaN, indicating that the Date object does not represent a specific instant of time.
This means that using math operations on a Date object will extract its Number value to work. That's why statements like +new Date() and Math.floor(new Date()) returns a Number.
As for '' + new Date(), the Date object returns its String value perhaps using its toString() function.
I was reading this answer to Hidden Features of JavaScript? and was perplexed by this behaviour:
> new Date
< Fri Feb 26 2016 21:15:43 GMT-0500 (EST)
> +new Date
< 1456539382581
< 0 + new Date + 0
"0Fri Feb 26 2016 21:17:39 GMT-0500 (EST)0"
So, the Date constructor returns an object which, when converted to a number via unary (but not via addition) returns a number representing the Unix Epoch.
How is this possible? Reading about the topic, it seems like JS has no support for operator overloading, or only a small amount if overloading non-operator functions (add, toString, whatever) counts.
JS doesn't seem to have any such function for unary + specifically (or number coersion at all, it seems), so how is this done?
Unary operator + converts its operand to a number if it isn't already.
So +new Date is similar to Number(new Date).
new Date() // Fri Feb 26 2016 21:45:32 GMT-0500 (EST)
Number(new Date()) // 1456541132899
+new Date() // 1456541132899
Update:
What's special about the Date object that makes calling Number on it return the Unix time?
Date objects are based on a time value that is the number of milliseconds since 1 January, 1970 UTC (From MDN). So, it makes sense when we ask it to convert it to a number, it returns us milliseconds.
Automatic type conversion of Dates.
The primitive numeric value of a Date object, returned by Date.prototype.getValue() is a Unix time stamp, the number of milliseconds since 1 January, 1970 UTC and is the value of a Date object converted to a number.
When converting an object to number following a unary + operator, the javascript engine explicitly asks the object to return a number, by calling the objects internal toPrimitive method with a hint value of "number" as described in section 7.1.1 of the ES6 standard. This mechanism converts Date objects to milliseconds after a unary + sign in fairly standard fashion.
So how to explain how Date objects become converted to a string when used as the operand of a non unary plus?. It would seem that for the non-unary case, type conversion requests an object's primitive value without supplying a result type hint and . . . Date provides an exotic toPrimitive function which converts dates to string by default instead of to number. Date and Symbol are special in this regard and differ from most other objects.
Here is a little description about unary plus from MDN:
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.
If the operator cannot parse a string/value, it returns NaN.
I have the following methods of obtaining a timestamp:
new Date().valueOf()
new Date().getTime()
Date.parse(new Date())
new Date() * 1
But I'm confused: why am I able to get a timestamp using the last method?
This is because the Date() object can be converted directly to a number (the timestamp), and when applying mathematical operators to it JavaScript converts this for us.
An even quicker way to get the timestamp is to use the Unary Plus:
+new Date();
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. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number.
– MDN's Unary Plus documentation.
The same applies with strings "1" * 1 equals 1 because JavaScript automatically converts "1" to a number because of the presence of the multiplication operator (*).
One of the weird things about JavaScript is that if you try and perform an operation between two variables, it will try to convert them to a type where it can perform this operation. But this can happen in different ways, so for example "2" * 2 === 4 is true, but so is "2" + 2 === "22" because it goes to the string version of the + operator first.
When you take a Date and try to do multiply or divide it, JavaScript will understand that as converting the Date to it's numerical timestamp value. Consequently the surprising outcome you see above.
However:
new Date() + 1
Results in "Tue Jul 07 2015 15:20:17 GMT+0100 (GMT Daylight Time)1" because the date can also be treated as a string.
This is one of the many quirks of JavaScript that will be helpful to understand when you run into that weird bug, but you would be well advised to avoid using in your code if you want to be able to understand it at a glance later ( spoiler warning: You do! )
I understand that using the "===" compares type, so running the following code results in "not equal" because it's comparing a number type to a string type.
var a = 20;
var b = "20";
if (a === b) {
alert("They are equal");
} else {
alert("They are not equal");
}
But I dont understand how using the "==" to compare only the value results in the "They are equal" message.
var a = 20;
var b = "20";
if (a == b) {
alert("They are equal");
} else {
alert("They are not equal");
}
How are the values equal? Isn't the string "20" stored as the ASCII characters 50 and 48 (0110010 and 0110000 in binary) and 20 stored as the actual binary number 0010100?
EDIT: Thanks everyone! I think all the responses are great and have helped me understand this much better.
The == operator compares only the values of the variables. If the types are different, a conversion is operated. So the number 20 is converted to the string "20" and the result is compared.
The === operator compares not only the values, but also the types, so no cast is operated. In this case "20" !== 20
The JavaScript engine sees the a as a number and casts the b to number before the valuation.
When type conversion is needed, JavaScript converts String, Number, Boolean, or Object operands as follows.
When comparing a number and a string, the string is converted to a number value. JavaScript attempts to convert the string numeric literal to a Number type value. First, a mathematical value is derived from the string numeric literal. Next, this value is rounded to nearest Number type value.
If one of the operands is Boolean, the Boolean operand is converted to 1 if it is true and +0 if it is false.
If an object is compared with a number or string, JavaScript attempts to return the default value for the object. Operators attempt to convert the object to a primitive value, a String or Number value, using the valueOf and toString methods of the objects. If this attempt to convert the object fails, a runtime error is generated.
The problem with the == comparison is that JavaScript version 1.2 doesn't perform type conversion, whereas versions 1.1 and 1.3 onwards do.
The === comparison has been available since version 1.3, and is the best way to check of two variables match.
If you need your code to be compatible with version 1.1, 1.2 and 1.3 versions of JavaScript code, you should ensure that the variables all match as if it was an === comparison that was being performed.
Part of the definition of "==" is that the values will be converted to the same types before comparison, when possible. This is true of many loosely typed languages.
Javascript is designed such that a string containing numbers is considered "equal" to that number. The reason for that is simplicity of use for the case of users entering a number into an input field and the site validates it in JS -- you don't have to cast the entered string to a number before comparing.
It simplifies a common use case, and the === operator still allows you to compare with the type considered as well.
As far as I know JavaScript does automatic data type conversion on the fly - so maybe the variables are casted to equivalent types automatically.