Hacker News new | past | comments | ask | show | jobs | submit login
The WHY of WAT - understanding why 'JavaScript is Crazy' (caplin.com)
82 points by amirhhz on Jan 27, 2012 | hide | past | favorite | 52 comments



> ... he pokes fun at some apparently crazy behaviours in Ruby and Javascript.

I am sorry, but that still is crazy behavior. You can excuse it with a historical perspective ("well it had to hide errors from users") or by explaining "the why" like you do, that still doesn't make that behavior less crazy.


Every single point in that article made complete sense, and yet it left me feeling even more convinced of Javascript's insanity.


Not trying to defend the craziness, but, when you are trying to do []+{} and "foo"-1, you can kinda expect unexpected results if you know that JS does type coercion.


That is not the problem here. The problem is that this might by the code piece "x + y" where x and y is in your scope and happens to be [] and {}. The resulting value is then highly confusing to a programmer. A language that enforces explicit type conversion (some call these strongly typed languages) would not allow this, but require you to write something like "string(x) + string(y)" if you really wanted such behaviour.

I think it is rather bad semantics actually.


I can't imagine a single situation where you expect variables used in a sum operation to be arrays/objects. That would be highly confusing.

You always have the option to use

    Number(x) + Number(y)
    (+x) + (+y)
    String(x) + String(y)


"I can't imagine a single situation where you expect variables used in a sum operation to be arrays/objects."

That's precisely the problem. You don't expect them, but there's nothing to prevent it from happening, so it does.

Your proposed solutions don't solve the problem, they occur too late. By the time you're adding together two non-numbers (and non-strings) you've already lost, trying desperately to cast them to numbers first is also wrong, along with so verbose that nobody will ever do it.


Yeah, that was stupid.

What I mean though is I can't imagine code that gives chance for this to happen. Putting an array where a number should be is a very visible mistake.


This is not "WHY", this is "HOW exactly". I bet the reason why JavaScript has these behaviors is due it being developed as a browser scripting language. Authors didn't want the entire script terminating because some part of it was buggy. This could have been handled by some clever isolation and error-recovery mechanism, but it wasn't. Probably due to time constraints.

These kinds of things are one of the reasons why I really don't like the idea of everything (including server-side and standalone apps) being written in JavaScript.


That's fair, but PHP has the same level of WTF, and is (I'd argue) less elegant than JS.


Sorry, I'm missing something. Is the grandparent a big advocate of PHP? Why is PHP being brought into this?


It's a language that is heavily used for server apps, which the top post was saying JS shouldn't do. My point was, quirks like these haven't outweighed the advantages of PHP, and I don't think they should for JS either.


This is only part of the why. The other part is the valueOf function which you can specify in order to control what the value of an object is when coerced.

So for instance:

    var arr1 = [1,2,3], arr2 = [1,2,3,4];
    console.log(arr1 + arr2); // "1,2,31,2,3,4"
    arr1.valueOf = function () { return this.length; };
    arr2.valueOf = arr1.valueOf;
    console.log(arr1 + arr2); // 7


text only cache, courtesy google: http://webcache.googleusercontent.com/search?q=cache:http://...

and a duckduckgo tip

    !cache http://blog.caplin.com/2012/01/27/the-why-of-wat/


Full version cache, so the lines aren't unreadably long:

http://webcache.googleusercontent.com/search?q=cache:http://...


The original presentation was nicely done, but knowing how things work in JavaScript (even though I don't know Ruby) meant I didn't exactly have that WTF-experience. This article explains it nicely to those who had.


I think this kind of misses the point. Even if you understand why JavaScript behaves this way, it doesn't mean that the behavior is sane.

JavaScript without type coercion would have been safer and saner in my opinion.


Type coertion is a language feature just like some other risky-yet-helpfull features. Take for example pointers: any programming language without pointer is safer†, but pointers help you express certain things concisely and thus avoid some classes of bugs. Heck, a knife with dull blade is safer just as well, but that doesn't increase its overall utility.

Compare with:

> UNIX was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things. — Doug Gwyn

--

†except that you can generate NullPtrException in the pointerless Java. Ask yourself, WAT?


That's awfully generic and doesn't address the criticism. What are the examples of useful type coertion? What do they achieve? Are there no better ways to achieve those same goals without introducing bug-prone, WAT-inducing behaviors?

For example, string concatenation could have been handled by a separate operator.


To be fair, Eich was required to imitate java and finish in a couple of weeks for marketing reasons, and string + int -> string was one of java's mistakes.


Nitpick: Java does have pointers in the sense of indirect references, so it makes perfect sense that a NullPointerException can exist, even if having nullable references in general is a bad idea.


Java has references but not pointers, in that you can't do arithmetic with them. This actually does increase safety substantially; you can still get a (badly-named) exception by trying to dereference a null reference, but it's a lot harder to turn what was supposed to be a pointer to an input buffer into a pointer to your program's executable code.


Pointer are incredibly more useful than type coercion. In my experience, it is only really useful for beginners who then don't have to know that "1" and 1 are different things. JavaScript has a basically useless == operator because of this.


Nitpick: dull blades are not safer.


Sub-nitpick: Depends on how you're handling the blade.

A dull blade on a round onion is not safer than a sharp blade on that onion. Running your hand across a dull blade is safer than running your hand against a sharp blade.

Javascript in a nutshell.


Knowing C but not JavaScript, I can think of uses for all operations that are defined on C pointers. Yet, I cannot come up with one for String - Number or Hash + Array. If you want to argue that they are useful shortcuts, I think examples would help the case.


Well I think that was 'designed' basically to cast any type to it's string representation. Also wanted to point that I used type coercion when is supposed to be used, and never got a bug of that nature in my code, but yes, you must get the coercion rules right from the beginning, and yes, javascript code could live perfectly with this 'feature'.


Well i'v never understood the problems with JavaScript but maybe it's because i haven't done things how other languages do it. But js is very "open" and bound free. Especially with functions and objects. They make sense to someone who is new to OOP. maybe its not follow how things are usually done in other languages but that does not mean its necessarily a bad thing. If you think something doesn't make sense that does not mean its wrong. i am learning c and i have to say typed variables must be faster but they are difficult to gasp at first. In fact its a nightmare to make variables of a certain type, it limits my thought process when i have to think what the variable's type is after every line of code. Strings look like a huge deal. The fact that i have to predetermine the length of a string is laughable. Its my string and it can be as long as i want it to be anywhere in my code. (yes i now sound immature but this is my experience until now, call it a rant if you may) Alot of things need to be known before we can write a meaningful program. Thats not the case with js or even with php to some extent.


These difficulties in C are not "craziness", they are for very good reasons.

Unbounded strings have much more complex and potentially less optimal semantics than bounded strings, need to be allocated in different ways, etc. C makes tight resource control possible, and to do that it sacrifices a lot of ease. You have to think about resources when programming. In many scenarios, this is a good thing.


>C makes tight resource control possible, and to do that it sacrifices a lot of ease.

I'm not a C programmer (yet), but I would say that depends on what you define as "easy" or "simple". What I am is an Arch Linux user, and I embrace KISS - Keep It Simple, Stupid. Arch understands "simple" as "technically elegant and uncomplicated", but that doesn't mean it's easy to understand or foolproof to use - for the inexperienced user, that is. C is an incredibly powerful tool exactly because it is this kind of simple.

What I also am is someone who learned programming with Python, and I initially couldn't understand the appeal of C-oid languages either. But I've since realized it's all about using the right tool for the job. A programmer is a mechanic, and a mechanic that only knows how to use a hammer is a pretty useless mechanic (in general, of course. If all you deal with are nails then it's not an impediment to your abilities).


There's of course the view that a programmer is a mathematician :-)

But I agree we need various tools to cover the necessary ground.


Yes, i agree. I was not offending C, i was just defending JS buy using C as an example. I have said this below but will say again. C is as much crazy to me as is JS to some other people. this does not make C evil.


> it limits my thought process when i have to think what the variable's type is after every line of code

Why do you feel the need to think about the variable's type on every line though? Since they're typed, you should pretty much know exactly what they are, instead of trying to figure it out. Since they're not dynamic, they're never changing.


let me give an example. there is no easy or straight forward way to make a string's length variable. i cannot for example do something like 'int string1[n]' where n is something i got through scanf. also there are different functions to get user's input for intigers and strings. Why would anyone have so many different things like scanf, getch, getche, gets, etc. why not make one simple function and take other things as an argument?

So i need to stop and think how can i input a variable from user, which function should i use. I was just defending js. I don't oppose C, i am just saying its about perspective. C is as much crazy to me as is JS to some other people. this does not make C evil.


One simple example: when you read a telephone number, you care very much whether it's a string or an integer. The reasons are:

- 004412......... and 4412..... are completely different things. You care also about how you annotate base of integers, because anything starting with "0" might be an 8-base integer.

- Even if we assumed local numbers don't start with 0, there are some places where such number doesn't fit into an integer. 32b int is only 10 digits in dec base.

So yes - whether it's C or JS you should very much care what the actual type is. This isn't very theoretic either. Some time ago, twitter started using id which were larger than 32b fields. Even though people should've been treating those ids simply as opaque strings, some used integers, leading to twitter client update panic.


well yes but i was talking about how it's stored in memory. Like in js all the numeric operations can be performed on strings that are just numbers. Think of it as an intelligent string that behaves according to it's contents. if it's contains an integer, it behaves like one. since there are finite number of types a variable can have, it shouldn't be a huge deal to automate this. But since this has not already been done, i am obviously missing something here.


No, it doesn't. If it's a string, it's a string: "1" + "1" -> "11". I know what you mean (it would if the first op wasn't a string), but see how this got confusing even in your short message. I'm still not sure why would you want to automate all types into a magic one that does what you want... unless you split all operators into N distinct ones giving you different results. But then you get the same result really - ops determine your results.

Again using phones example:

country + area + ending

is different depending on what the actual types are. This is simply an issue we cannot ignore. In this case I'm expecting the concatenation and the result cannot depend on "contents of the string".


I wouldn't really consider C that much of a statically typed language, with all the pointers and casting and low level stuff. Have a look at Haskell/ML/Ocaml if you really want to see a type system that will blow your mind :)


You can say that this is more of a first world developer problem but i am still an ammature (as you might have guessed) and i have started to kind of dislike typed languages. i like my space and freedom to put text or integer or float or blob or raw binary data in a variable. because mostly it all ends to string, everything can be a string, numbers, floats, characters all of them. so why not make devs life easy by making everything a string?


Because in strongly typed languages the compiler is able to hunt down the most of the bugs for you in milliseconds. That's why haskell programmers suggest that if a haskell program compiles gracefully, you can assume is mostly correct and bug free.


Because someone is paying for the code you write to do predictable things that they want.


"The fact that i have to predetermine the length of a string is laughable... Thats not the case with js or even with php to some extent."

It's not laughable. Most implementations of JS and PHP are probably written in C or C++. While using dynamically allocated strings in higher level languages like these are indeed easier than null terminated strings in C, at some point someone somewhere had to write code at a lower level to support this.


> at some point someone somewhere had to write code at a lower level to support this

Yes that is something i totally agree with. In fact that's why i only supported js and not hate c. Because somewhere it has to be done and c is efficient in dealing with memory allocations whereas js deals with front-end mechanics. But to say that js is 'crazy' is something beyond me. every language has its ways and it depends on what 'level' (high, low, machine) that language works in computer hierarchy.

Comparing high level language like js to lower level language (like c++, java, etc) on their syntax or how it deals with objects/arrays makes no sense.


Well, given that javascript was designed in somehow less time and with less resources than superior languages it has obviously some inconsistences and everybody agrees on that. On the other side if you know the language really well you can avoid the most of the problem it has. I like your point of 'keep it real' but you need to accept that the language is far from 100% correct.


>Error establishing a database connection

Does anyone have a mirror?


Yes, sorry, Caplin server's didn't expect the load! It's being worked on.


> It can be a prefix ‘this number is positive’ operator where it operates on a single number.

`+` in this context is the "Unary + Operator" which coerces a value to a number via the internal `toNumber` method of the operand.

It doesn't make the number positive:

    node> +-1 // -1


Automatic type coercion feels like a double-barreled shotgun, with one of the barrels pointed back at you:

0. Is only marginally useful 1. You have to be careful with what are you loading, and where 2. Will sooner or later blow up in your face


The syntax doesn't bug me too much. Most of it is documented fairly well. The craziest thing about JavaScript is a lack of any good online reference for their classes and methods. JavaScript documentation usually just resorts to a key example or a brief description without covering all the details.



Add “MDN” to any javascript-related google query to get the MDN page at the top of the results page. Examples: “operator precedence mdn”, “string mdn”, “slice mdn”.


I always end up googling what i need and i find it rather easily. I find it more easy to fill in my query with keywords ans answer is usually in top5 results :)


don't explain it! you are killing the fun...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: