Zeros in JavaScript(zero.milosz.ca)
zero.milosz.ca
Zeros in JavaScript
http://zero.milosz.ca
17 comments
Some explanations: The rule of thumb is that, == does type coercion only when at least one of operands is primitive (non-Object), and does only the identity check otherwise. Therefore:
[1] != [1] since both [1] are distinct arrays; [1] == 1 since 1 is primitive so [1] gets converted to primitive, in this case, '1', and '1' == 1. (The conversion to primitive is complicated, mainly because it has to select between ToNumber and ToString depending on the context. See Section 9.1 of ECMA-262 5th edition.) Likewise, [] == 0 since [] gets converted to '' and coerced to 0.
NaN != NaN is a well-known facet of IEEE 754 floating point system, and you'll see similar phenomenon in SQL's NULL handling.
[0] + [0] == '00' since both operands are coerced to string (no numeric operands there, so we assume both operands will eventually become string); [0] * [0] == 0 since both operands are coerced to number (no multiplication on string).
...Yeah, I agree on your thesis that ECMA-262 is seriously f*cked up.
[1] != [1] since both [1] are distinct arrays; [1] == 1 since 1 is primitive so [1] gets converted to primitive, in this case, '1', and '1' == 1. (The conversion to primitive is complicated, mainly because it has to select between ToNumber and ToString depending on the context. See Section 9.1 of ECMA-262 5th edition.) Likewise, [] == 0 since [] gets converted to '' and coerced to 0.
NaN != NaN is a well-known facet of IEEE 754 floating point system, and you'll see similar phenomenon in SQL's NULL handling.
[0] + [0] == '00' since both operands are coerced to string (no numeric operands there, so we assume both operands will eventually become string); [0] * [0] == 0 since both operands are coerced to number (no multiplication on string).
...Yeah, I agree on your thesis that ECMA-262 is seriously f*cked up.
NaN !== NaN is intended, and is the same in any other language that has NaN. It is never supposed to be equal to anything else, not even itself.
As for the rest of those quirks, they mainly have to do with type coercion, the rules for which are not as difficult to learn as the whole table in the submission. The fact that type coercion is performed for == is why nobody uses ==. You also should never try + or * on arrays (and why would you?). With some simple best practices, you never end up running into most of these quirks in practice.
As for the rest of those quirks, they mainly have to do with type coercion, the rules for which are not as difficult to learn as the whole table in the submission. The fact that type coercion is performed for == is why nobody uses ==. You also should never try + or * on arrays (and why would you?). With some simple best practices, you never end up running into most of these quirks in practice.
Another fun thing about NaN is that typeof NaN === 'number'. Which, you know... seems counterintuitive based on the fact that NaN means "Not a number".
Eh. 'number' means 'IEEE 754 floating point value' and NaN is certainly one of those. Abbreviations are tricky.
Yeah, I understand why. I was just pointing out that on the surface, it seems kind of weird.
There's a reason why Perl separates numeric and string operators, and it's not just to make it confusing for people.
NaN is mostly equivalent to the _mathematical_ concept of undefined. It cannot be equal to anything, even itself, because there are multiple mathematical operations that can result in NaN that are not equivalent in value. Considering their result equivalent would be in error.
in a NaN === NaN world, (1/0)*0 === 0/0 is true.
in a NaN === NaN world, (1/0)*0 === 0/0 is true.
As others have pointed out, NaN == NaN being false is not surprising (at least according to IEEE floating point semantics ;).
I kinda makes sense if you consider that both 0/0 and Infinity0 evaluate to NaN. `0/0 == Infinity0` being true would be an even weirder behaviour.
I kinda makes sense if you consider that both 0/0 and Infinity0 evaluate to NaN. `0/0 == Infinity0` being true would be an even weirder behaviour.
NaN == NaN should return false.
As a Pythonista Javascript is really strange. Let's combine two arrays with a + b. Wait, why is it now a string? Why did it just create a undefined.jpg when I run filename + '.jpg'? Ah damn, I named it filepath. I guess I check if this object is empty by comparing it to false, works for arrays right? Except it doesn't and it doesn't work for arrays either because they might contain a 0.
The lesson is, always look for a method that does what you want.
The lesson is, always look for a method that does what you want.
You call it strange, I call it broken. Python has strong types, so does Erlang. Javascript has weak types and I don't like it.
Whether one can avoid it or not is a different argument, as obviously there aren't that many choices on the browser, but I often argue it is a broken behavior, it annoys me every time I have to use Javascript.
Whether one can avoid it or not is a different argument, as obviously there aren't that many choices on the browser, but I often argue it is a broken behavior, it annoys me every time I have to use Javascript.
I program JS as my day job. It's a broken POS. You can do cool things with it but nothing can disguise the fact that it's only popular due to an accident of history, not because it's an appropriate language for the tasks it's used for.
You really wouldn't want an empty object to be equal to zero, since it might have a prototype that gives it functionality (and having the behavior conditional upon that would make it preposterously complicated to use correctly).
The real mistake was making [] equal zero.
The real mistake was making [] equal zero.
[] doesn't equal zero, but '' does, and [] is coerced to '' which is coerced to 0, IIRC.
What's really interesting thing is that all numeric coercions go through a string coercion, and that coercion doesn't (at least in Chrome and Firefox) have to even return a string. Presumably, the toString() method is run repeatedly until either a string or a number comes out.
So a simple fraction type can be done like this:
So a simple fraction type can be done like this:
function Fraction(n, d) {
this.n = n;
this.d = d;
}
Fraction.prototype.toString = function() {
return this.n / this.d;
};
//Demo
var x = new Fraction(1, 2);
alert(x * 38); //19
alert(x + x); //1The undefined.jpg thing won't happen for variables in strict mode, it'll error.
[].length is what you want for the second. IIRC [] isn't false in Python either.
[].length is what you want for the second. IIRC [] isn't false in Python either.
[] is false in Python; so are other empty aggregates like () and {}; collection types implemented in Python typically follow the same pattern. Thus:
>>> if (): print "tuple"
>>> if []: print "list"
>>> if {}: print "dict"
>>> if set(): print "set"
>>> if "": print "string"
>>> import collections
>>> if collections.Counter(): print "counter"
>>> if collections.deque(): print "deque"
>>>
(Observe that none of these prints anything.)Huh, I recall [] not working. Interesting.
[] is false in Python, along with most empty types.
http://ideone.com/ROMcag
http://ideone.com/ROMcag
[deleted]
Chrome: "This page is in Haitian. Would you like to translate it?"
It might as well be.
It might as well be.
You can submit the error, with the option of declaring what language the page is really in.
Unfortunately, "JavaScript" isn't in the list.
Unfortunately, "JavaScript" isn't in the list.
I met with this message as well.
me as well. very funny
I honestly have no idea what's so confusing. I've been working with javascript for over a decade and have NONE of this memorized, and I never look it up or check it in the repl. It's simply not an issue if you're using jshint and unit testing your code.
If you come from a static language background and you keep expecting a type-checker will save you from doing silly things like adding arrays to strings, you're always going to hate Javascript. It's a dynamically typed language, and so you have to learn the quality-control tools and practices for dynamically typed languages.
If you come from a static language background and you keep expecting a type-checker will save you from doing silly things like adding arrays to strings, you're always going to hate Javascript. It's a dynamically typed language, and so you have to learn the quality-control tools and practices for dynamically typed languages.
> If you come from a static language background and you keep expecting a type-checker will save you from doing silly things like adding arrays to strings, you're always going to hate Javascript.
Hmm funny I come from a dynamic language background and never had a problem with the language telling me adding an empty list to an empty list should somehow be empty string. That is batshit crazy. Those are not silly things those are basic 101 strong type system checks that very dynamics languages like Ruby and Python can do.
Hmm funny I come from a dynamic language background and never had a problem with the language telling me adding an empty list to an empty list should somehow be empty string. That is batshit crazy. Those are not silly things those are basic 101 strong type system checks that very dynamics languages like Ruby and Python can do.
"Strong-typing vs weak-typing" is actually irrelevant. It's still an error at run-time, and unless your quality control tools and practices actually run the code (like unit tests do), you're not going to know about them.
As you move beyond native types, duck-typing (like in python) completely subverts the strong type-checks anyway.
As you move beyond native types, duck-typing (like in python) completely subverts the strong type-checks anyway.
> It's a dynamically typed language [...]
I don't think being a dynamically typed language has anything to do with having weird type coercion rules for the most basic operations. Nor with allowing seemingly invalid operations (e.g. adding arrays and strings) and returning a value instead of raising an error on those cases.
> I honestly have no idea what's so confusing.
Really? Comparing JS's == and + operators to other languages' (dynamically typed or not), wouldn't you say that JS's semantics are more complicated/confusing than what they should be?
I don't think being a dynamically typed language has anything to do with having weird type coercion rules for the most basic operations. Nor with allowing seemingly invalid operations (e.g. adding arrays and strings) and returning a value instead of raising an error on those cases.
> I honestly have no idea what's so confusing.
Really? Comparing JS's == and + operators to other languages' (dynamically typed or not), wouldn't you say that JS's semantics are more complicated/confusing than what they should be?
You're not supposed to use ==. It's there only for backwards compatibility.
Replace == by some other comparison operator like < or > if you prefer. The weird coercion rules still apply.
>>> '5' < [6]
trueWhy are you comparing a string to an array with a less than operator? when would that ever happen legitimately?
Why would you expect any language to do something that made sense doing that?
Why would you expect any language to do something that made sense doing that?
> when would that ever happen legitimately?
Never. Aka, on buggy code.
Instead of asking when that happens legitimately, why don't you ask why does it evaluate to a legitimate value?
> Why would you expect any language to do something that made sense doing that?
Because raising an error in those cases would:
1. Make the language simpler and easier to understand (and to implement). No coercion rules, not guessing what some other developer meant when they wrote `a == 0` (are they asking for numeric equality, or could `a` be a string or a boolean value too?).
2. Make it easier to identify the bug in case it should happen.
Let me ask you, do you also think syntax errors are unnecessary too? Because, why would anyone write a program with invalid syntax? Why would one expect any language to do something that made sense, like not compiling/running the code, in those cases? Wouldn't it be better if, for example, in case a line contains a syntactic error, the interpreter would just discard that like and run the program anyway?
Never. Aka, on buggy code.
Instead of asking when that happens legitimately, why don't you ask why does it evaluate to a legitimate value?
> Why would you expect any language to do something that made sense doing that?
Because raising an error in those cases would:
1. Make the language simpler and easier to understand (and to implement). No coercion rules, not guessing what some other developer meant when they wrote `a == 0` (are they asking for numeric equality, or could `a` be a string or a boolean value too?).
2. Make it easier to identify the bug in case it should happen.
Let me ask you, do you also think syntax errors are unnecessary too? Because, why would anyone write a program with invalid syntax? Why would one expect any language to do something that made sense, like not compiling/running the code, in those cases? Wouldn't it be better if, for example, in case a line contains a syntactic error, the interpreter would just discard that like and run the program anyway?
You can't make history something it's not. You might or might not remember visiting the web soon after javascript was released. It involved a lot of broken code, and a lot of error pop ups. Javascript was, historically, a dumb easy scripting language for simple interactive effects on the web.
When we're talking about a script that is downloaded from a server, and runs in a browser, that is a much different kind of situation than a programming language usually encounters. It is in the browser maker's interest to be liberal about what it accepts. this is the core reason for the success of html, and the failure of xhtml.
as much as the makers of javascript would like to remove certain problematic features, they cannot without breaking old existing content.
Now if you want a strict language in the browser that disallows that sort of nonsense, it's easy. Just run JSLINT on your code before deploying it. JSLint considers as an error, pretty much all of your complaints here. If you don't like some aspect of javascript, you can simply not use it. If there's something jslint doesn't catch, I suppose you could always add stuff to jslint. JSLINT is your static compiler.
There are solutions to your pain and suffering. you don't have to endure it.
When we're talking about a script that is downloaded from a server, and runs in a browser, that is a much different kind of situation than a programming language usually encounters. It is in the browser maker's interest to be liberal about what it accepts. this is the core reason for the success of html, and the failure of xhtml.
as much as the makers of javascript would like to remove certain problematic features, they cannot without breaking old existing content.
Now if you want a strict language in the browser that disallows that sort of nonsense, it's easy. Just run JSLINT on your code before deploying it. JSLint considers as an error, pretty much all of your complaints here. If you don't like some aspect of javascript, you can simply not use it. If there's something jslint doesn't catch, I suppose you could always add stuff to jslint. JSLINT is your static compiler.
There are solutions to your pain and suffering. you don't have to endure it.
Dynamic typing (a type belongs to the value, not the variable or "slot") is not same as weak typing (a type may get silently messed up). Python is a good example of dynamically but yet strongly typed language. There exists a good argument against the whole notion of "strong"/"weak" distinction (mainly because it is not a bipartite property, and well-defined type coercion can be regarded as safe) but the main idea holds.
So, use triple-equals when you don't want type coercion?
My favorite bit is where all of these are true:
'1' == 1
'1' == [1]
'1' == true
1 == [1]
1 == true
[1] == true
But this is false: [1] == [1]Why would it be true? Two different instances of an object don't equal in JS. It compares identity, not value, when dealing with non-value types.
> Why would it be true?
It is funny that you are asking why would [1] == [1] possibly considered to be true.
Let's see in a language with a sane and consistent typing system like Python:
It is funny that you are asking why would [1] == [1] possibly considered to be true.
Let's see in a language with a sane and consistent typing system like Python:
In [1]: [1]==[1]
Out[1]: True
Ok, let's do a crazy language from Sweden also with dynamic types but which are sane and consistent, like Erlang: 1> [1] == [1].
true
Surely it will be broken in Ruby: irb(main):001:0> [1] == [1]
=> true
Nah clearly it should be false, these crazy languages just haven't heard about objects and identities and such.Why are you being a dick? He explained the difference accurately - JS compares objects as individual objects. Arrays are objects. The other languages you cited do not work that way.
Here's another example:
Here's another example:
4 == 4 // true
a = new Number(4);
b = new Number(4);
a == b // false
a == a // true
a.valueOf() // 4
b.valueOf() // 4
a.valueOf() == b.valueOf() // true
And if this isn't clear yet: a = {}
b = {}
a == a // true
a == b // falseRather his tone of "Why would it be true?" sounded dick-ish. As in "How could possibly one consider [1] == [1] be true, are you crazy? It should obviously be false".
So I gave a couple of examples from other dynamic languages where the the sane behavior is "obvious".
I am not being a dick I am saying the language is broken. Explaining the historical context or the internal implementation of it doesn't make it unbroken. Like one can explain why COBOL uses this construct or that and how it came to be, doesn't make COBOL better or more appealing. One of course might not have a choice and be stuck using it but lying to oneself about how awesome it is, is not necessary.
> The other languages you cited do not work that way.
The don't, and I like how they work better.
Now whether one has a choice to use or not use JS is a different topic. Usually there is no choice on the client side. But somehow extolling Javascript typing rules as being sane, making sense, or as someone below put it "brilliant" is a bit silly.
So I gave a couple of examples from other dynamic languages where the the sane behavior is "obvious".
I am not being a dick I am saying the language is broken. Explaining the historical context or the internal implementation of it doesn't make it unbroken. Like one can explain why COBOL uses this construct or that and how it came to be, doesn't make COBOL better or more appealing. One of course might not have a choice and be stuck using it but lying to oneself about how awesome it is, is not necessary.
> The other languages you cited do not work that way.
The don't, and I like how they work better.
Now whether one has a choice to use or not use JS is a different topic. Usually there is no choice on the client side. But somehow extolling Javascript typing rules as being sane, making sense, or as someone below put it "brilliant" is a bit silly.
No, he didn't ask it like that at all. You're putting words in his mouth instead of reading the sentence in the context of the two sentences that followed it, which made it a completely reasonable question.
I think the point is that it's interesting that a bunch of textually-different things are considered equal, but the one textually identical pair are considered not equal.
Because equality should be transitive. If a == b and b == c, then it should be the case that a == c.
[1] == 1 and 1 == [1], so it should be the case that [1] == [1].
Just because it's what happens when you apply the rules of the language doesn't mean it actually makes sense.
[1] == 1 and 1 == [1], so it should be the case that [1] == [1].
Just because it's what happens when you apply the rules of the language doesn't mean it actually makes sense.
A better rule is to use triple-equals always, and manually coerce if you really mean it.
This is a dangerous rule; if you put this rule in the hands of a programmer who is not used to Javascript and doesn't really understand the type system, you can just as easily run into problems.
This is because you require the programmer to always understand the output (and defaults) of every call made. Sometimes it's undefined. Sometimes it's null. Sometimes it's empty string. This takes experience.
Example, the default for getAttribute is null, but an undefined property is undefined:
This is because you require the programmer to always understand the output (and defaults) of every call made. Sometimes it's undefined. Sometimes it's null. Sometimes it's empty string. This takes experience.
Example, the default for getAttribute is null, but an undefined property is undefined:
document.body.getAttribute("test"); // null
document.body.test; // undefined
Except if it's a special property, then getAttribute might still be null, but the property empty string: var input = document.createElement("input");
input.getAttribute("value"); // null
input.value; // ""
Remember, "" !== null and null !== undefined.That only solves part of the problem. Coercion also happens for other operators, which ought to have at least had === equivalents. I.e.
5 + (10 * [2]) + (9 + [1/'']) // 259Infinity
5 ~+ (10 ~* [2]) ~+ (9 ~+ [1 ~/ '']) // throw exceptionYes, or you can use CoffeeScripts which automatically translates == into ===
Yes, highly recommended. Just look at that chart, insanity!
A lot of this is sort of strange or unexpected, and that's obviously not a good thing. But 99% of the operations in that table are ones that I would never be doing in the first place.
`[null] + {} == 'null[object Object]'`? Okay, fine. I might not have known that off the top of my head, but I also make it a habit not to add/concat arrays and objects.
Unexpected type coercion is probably responsible for about 1% of the bugs I write. It's just not that big of a deal once you learn the common cases (`'1' == 1`, etc.)
`[null] + {} == 'null[object Object]'`? Okay, fine. I might not have known that off the top of my head, but I also make it a habit not to add/concat arrays and objects.
Unexpected type coercion is probably responsible for about 1% of the bugs I write. It's just not that big of a deal once you learn the common cases (`'1' == 1`, etc.)
Ugh. Many parts of javascript are nice but things like this (''==0?) make me wish for a browser-supported language that was clean.
Since comparing strings and numbers generally doesn't make a lot of sense, you could just consider it a case of "undefined behavior". As many other people will write: There's only one case I can think of where the unsafe-equals operator is reasonable and that's `a == null` to check for null/undefined.
Most languages call those situations by the name "runtime error", that is, when it is even possible that they happen at runtime.
Now, I understand that javascript runs in a completely different kind of environment, and it does have the liberty of making things differently, up to a certain point. But making '' == 0 true may be a bit too far.. And making [1] == 1 true is clearly too far.
Now, I understand that javascript runs in a completely different kind of environment, and it does have the liberty of making things differently, up to a certain point. But making '' == 0 true may be a bit too far.. And making [1] == 1 true is clearly too far.
Yep. Along with `== null`. I also only use "==" with `typeof` since `typeof` always returns a string.
Yea, or you could use "===".
like what?
php?
visual basic?
c?
java?
define "clean" and name one language in the history of computing that actually fits that definition.
define "clean" and name one language in the history of computing that actually fits that definition.
I'll define "clean" as a language that has been intentionally designed with a goal to make language features interact in intuitive ways - i.e., that if something looks like X, then it also acts like X; and also behave safely, i.e., undefined behavior is minimized or eliminated if possible.
'Evolved' languages tend to be less clean than 'designed' ones, and also any language accumulates cruft with time if features are added carelessly - for example, C++ can never be 'clean' even if C++11 tries to be that way, because compatibility.
Python, go, Haskell are much cleaner than JS. I'm not claiming that those languages are perfect, they definitely aren't, but there is a significant difference - just as in the saying that [earth is flat] is wrong, [earth is a sphere] is wrong, but they're nowhere near equally wrong.
'Evolved' languages tend to be less clean than 'designed' ones, and also any language accumulates cruft with time if features are added carelessly - for example, C++ can never be 'clean' even if C++11 tries to be that way, because compatibility.
Python, go, Haskell are much cleaner than JS. I'm not claiming that those languages are perfect, they definitely aren't, but there is a significant difference - just as in the saying that [earth is flat] is wrong, [earth is a sphere] is wrong, but they're nowhere near equally wrong.
Python, Ruby, Dart just to name a few from the top of my head.
EDIT: removed Java, Rust and Go
EDIT: removed Java, Rust and Go
You forgot to define "clean".
Also, java is in your list. Java had its chance. it failed. did you forget that? So has Dart. how's dart doing?
Rust as a web scripting language doesn't even make sense.
Lua.
As much as I like lua, it doesn't really meet the challenge I set forth. For one, you forgot to define "clean".
For another, if you put lua in the browser instead of javascript, how long do you think it will be before lua starts growing horrible warts as well?
For another, if you put lua in the browser instead of javascript, how long do you think it will be before lua starts growing horrible warts as well?
...and that's why no one but brand new beginners use "==". If it was up to me, "use strict" would turn "===" into "==" and there would be no "===".
It's too late now because it would break a lot of applications, so a new mode might be required, like "use not-completely-broken-comparisons-by-default".
It's too late now because it would break a lot of applications, so a new mode might be required, like "use not-completely-broken-comparisons-by-default".
[deleted]
CoffeeScript does that.
Yup, but CoffeeScript introduces 99 other ways for beginners to create awful code, it's way easier to shoot yourself in the foot than with just JavaScript. I still prefer CoffeeScript, though.
You know you're on HN when people are defending this broken aspect of JavaScript, yet hate on the same broken aspect of PHP.
I had to laugh when I saw this. It made me think of the Joshua Bloch interview in Coders at Work:
> Seibel: I was reading Java Puzzlers and Effective Java and it struck me that there are a lot of little weird corners for a language that started out so simple.
> Bloch: There are weird corners, yes, but that's just a fact of life; all languages have them. You haven't seen a book called C Puzzlers. Why not?
> Seibel: Because it's all puzzlers.
> Bloch: Yep. It would take up a shelf. In Java, the puzzlers are worth collecting precisely because you think of it as a simple language. Every language has its corner cases and Java has few enough that they're for the most part fun and interesting.
Interesting, maybe. But I hope people are not using all of these. [0]
[0] http://tldp.org/LDP/abs/html/exit-status.html
> Seibel: I was reading Java Puzzlers and Effective Java and it struck me that there are a lot of little weird corners for a language that started out so simple.
> Bloch: There are weird corners, yes, but that's just a fact of life; all languages have them. You haven't seen a book called C Puzzlers. Why not?
> Seibel: Because it's all puzzlers.
> Bloch: Yep. It would take up a shelf. In Java, the puzzlers are worth collecting precisely because you think of it as a simple language. Every language has its corner cases and Java has few enough that they're for the most part fun and interesting.
Interesting, maybe. But I hope people are not using all of these. [0]
[0] http://tldp.org/LDP/abs/html/exit-status.html
Reminds me of my favourite Javascript trivia question:
What two values for a & b meet the following?
> a === b
true
> Number(a) === a
true
> Number(b) === b
true
> a + b === a
true
> (1 / a) === (1 / b)
false
> a === b
true
> Number(a) === a
true
> Number(b) === b
true
> a + b === a
true
> (1 / a) === (1 / b)
false
Edit: SPOILER ALERT
0 and -0.
I never knew about this until I read a shim someone wrote for Object.is().
0 and -0.
I never knew about this until I read a shim someone wrote for Object.is().
I think this is brilliant. Most programmers prefer code to be more readable for computers than for humans. I think the problem is that we grow up with the notion that computer programs have to be very strict, in syntax, types, comparisons etc. Is there really such a need?
It was for a similar reason that many people used to like XHTML over HTML. Not always because they needed to validate it, but to please the computer.
It was for a similar reason that many people used to like XHTML over HTML. Not always because they needed to validate it, but to please the computer.
> Is there really such a need?
Yes.
Because programs, unless they deal with machine learning, statistics or other intentional approximations, deal with _strict_ things.
If you put $0.5 in an account you don't expect to find $0.2 there when you read it back or find "Hi Jim" there. You expect to find $0.5, when you seek to byte offset 19553 in the file you expect to read starting with byte 19553 on next read not "something in the vicinity of byte 19553".
[] + [] should not be '', never, it never makes sense, it is not brilliant it is rather profoundly stupid.
Ok, language is broken, we established it, let's take a look at the library functions. At least there cooler heads prevailed:
Yes.
Because programs, unless they deal with machine learning, statistics or other intentional approximations, deal with _strict_ things.
If you put $0.5 in an account you don't expect to find $0.2 there when you read it back or find "Hi Jim" there. You expect to find $0.5, when you seek to byte offset 19553 in the file you expect to read starting with byte 19553 on next read not "something in the vicinity of byte 19553".
[] + [] should not be '', never, it never makes sense, it is not brilliant it is rather profoundly stupid.
Ok, language is broken, we established it, let's take a look at the library functions. At least there cooler heads prevailed:
$ node
> [1,10,9,-3,-4].sort()
[ -3, -4, 1, 10, 9 ]
Nope, they didn't.My favorite library strangeness is:
> [1, 4, 9].map(sqrt)
[1, 2, 3]
> ['1', '2', '3'].map(parseInt)
[1, NaN, NaN]
cf. http://stackoverflow.com/questions/262427/javascript-arrayma...As programmers we all know that Javascript has some crazy edge cases.
I'm not actually all that impressed by this illustration of Javascript's equality rules. This makes it look crazy when in fact it just gives the many edge cases much stronger visual weight.
The truth is, Javascript has lent strongly toward being natural in many of the most common cases -- things like being able to do `args = args || []` or simply prepending `!` to anything. Then, sometimes when you end up comparing NaN to undefined you aren't sure what the result should be or how you ended up there.
Funny thing is that often when I've run into those problems myself, I pull on the thread and find it was really caused by my own poor design somewhere else.
I'm not actually all that impressed by this illustration of Javascript's equality rules. This makes it look crazy when in fact it just gives the many edge cases much stronger visual weight.
The truth is, Javascript has lent strongly toward being natural in many of the most common cases -- things like being able to do `args = args || []` or simply prepending `!` to anything. Then, sometimes when you end up comparing NaN to undefined you aren't sure what the result should be or how you ended up there.
Funny thing is that often when I've run into those problems myself, I pull on the thread and find it was really caused by my own poor design somewhere else.
I prefer rigour for my own sanity rather than the computer's sake. In scala if I make a typo somewhere I get a compiler error that tells me the relevant line. In javascript I get "undefined has no property 'blah'", on a completely different line, at runtime.
Most programmers prefer code to be more readable for computers than for humans.
They do? How can I stop them all?
They do? How can I stop them all?
you're close, but you're not quiet there.
Programmers want code to be readable to an IDE.
IDE's can parse, interpret, precompile, and suggest.
Languages that are very wishy washy and dynamic like javascript are absolute hell for an IDE.
Programmers want code to be readable to an IDE.
IDE's can parse, interpret, precompile, and suggest.
Languages that are very wishy washy and dynamic like javascript are absolute hell for an IDE.
It's almost depressing. It must have taken significantly more work to embed these ludicrous rules when designing the language!
It didn't. The coercing rules are fairly predictable.
The coercing rules are fairly predictable, but oftentimes incomprehensible until you understand what's happening behind the scenes.
It's one of the biggest weaknesses of JavaScript. Much bigger than callback hell, garbage collection cycles etc.
My preferred style uses Array.prototype.join('') for string concatenation, non-coercive equality operations, and only using the + operator when doing math. It's a little cumbersome, but avoids ambiguity upon reading (and in the case of string concatenation, can be faster).
It's one of the biggest weaknesses of JavaScript. Much bigger than callback hell, garbage collection cycles etc.
My preferred style uses Array.prototype.join('') for string concatenation, non-coercive equality operations, and only using the + operator when doing math. It's a little cumbersome, but avoids ambiguity upon reading (and in the case of string concatenation, can be faster).
> and in the case of string concatenation, can be faster
myth: http://jsperf.com/array-join-vs-string-connect/37
myth: http://jsperf.com/array-join-vs-string-connect/37
In some cases, nocopy join is faster.
Thus.
"Can be" faster.
But most people do string concatenation in situations where performance of the concatenation really doesn't quite matter so much. I optimize for readability, understandability, and prevention of stupid silly mistakes first. Performance comes later.
Thus.
"Can be" faster.
But most people do string concatenation in situations where performance of the concatenation really doesn't quite matter so much. I optimize for readability, understandability, and prevention of stupid silly mistakes first. Performance comes later.
Here's the underlying rules of how "x == y" works: http://ecma-international.org/ecma-262/5.1/#sec-11.9.3
Weak typing and automatic coercions lead to some confusing results, but JS fares better than PHP.
Weak typing and automatic coercions lead to some confusing results, but JS fares better than PHP.
Everybody who writes JS should use something like jslint or jshint. JS has ugly parts, but most can be avoided easily.
what does mean 0[object Object]?
goofy plz
[1] == [1] is false, but [1] == 1 and 1 == [1]?
[0] == [0] is false, but [0] == '0' and '0' == [0]?
[] == [] is false but [] == 0 and 0 == []?
NaN === NaN is false?
[0] + [0] = '00', but [0] * [0] = 0?
Who designed this crazy language? It seems to take every quirk of every other language and combine them in the weirdest way possible.
[] == [] is false, so it must be comparing pointers, right? Common gotcha of Java, etc.
...Wait, NaN === NaN is false.