6 ms·
WTFJS – a list of funny and tricky JavaScript examples
- brudgers 9y agoMore WTF, https://wtfjs.com/ https://wtfjs.com/
- uwu 9y ago> Object.create(Array).length === 1 //true it bothers me how the examples are often misleading or just misusing language features but people who don't know the language will gladly agree with them and have their "js sucks" belief reinforced
- tambourine_man 9y agoAgreed, although some things like: NaN === NaN // -> false Are pretty f*&^%$ up, no matter how you look at them Edit: well, apparently there is a non f&^%$ up way to look at it: https://news.ycombinator.com/item?id=14891810 https://news.ycombinator.com/item?id=14891810
- roywiggins 9y agoThat's just normal floating point behavior. NaN isn't equal to anything, not even itself. It's in the standard.
- tambourine_man 9y agoFloating point can be a bit mind bending. Still, something not being equal to itself almost pushes the barrier into philosophy.
- fmihaila 9y agoNaN is not a name for one thing. You could think of not a number as not any particular thing. There is no comparison with itself, because there is no it.
- goatlover 9y agoHow is isNaN() implemented?
- Gaelan 9y agofunction isNaN(x) { return x !== x } It’s a native browser function so it may not actually be done that way, but that’s one way you could do it.
- tambourine_man 9y agoWe really are deep in the realm of Philosophy.
- roywiggins 9y agoAs long as you can define what's going on rigorously, it's just mathematics :) The equality operator means just what I choose it to mean- neither more nor less, as Humpty Dumpty would say. Also fun: (NaN < x) should be false for every x, and (NaN > x) should be false for every x. It's not a number, so it's not less than or greater than any number. But then by process of elimination, NaN == x for every x. Which is obviously nonsense. So equality and comparison is completely "broken" anyway when you start comparing NaN to things.
- aisofteng 9y agoThat's part of IEEE 754.
- tambourine_man 9y agoI didn't know it was part of IEEE 754, thanks. So JS is not alone in this.
- xyclos 9y agoNaN is meant to represent a non-sensical mathematical operation (like divide by 0). One non-sensical mathematical operation is not the same as some other non-sensical mathematical operation (1/0 !== Infinity/Infinity)
- Pigo 9y agoThat's a good point, a lot of this seems like it can be explained with some context or just asking why you'd ever want to do that.
- tambourine_man 9y agoThat's a good explanation, thanks.
- justinpombrio 9y agoNor is it the same as the same non-sensical mathematical operator :-) 1/0 !== 1/0
- tambourine_man 9y agoThat's mad. In JS, 1/0 is Infinity, not Undefined. And Infinity is not equal to itself.
- gmiller123456 9y ago>NaN is meant to represent a non-sensical mathematical operation This is not a very good explanation. NaN is used to represent a nonsensical value. By your explanation (1/0 === 1/0) should be true since they represent the same invalid opperation. The fact that NaN != NaN is not meant to mean anything, it is merely defined that way to prevent a class of bugs from occurring. Anyone not familiar with the definition is correct to be confused by it. I'd think if the spec was designed today, this special case (hack) wouldn't be there and we'd have exceptions in its place.
- fny 9y agoThere's a really great SO on why this is an IEEE standard: https://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values https://stackoverflow.com/questions/1565164/what-is-the-rati...
- tambourine_man 9y agoGreat discussion indeed. I was thinking along the same lines, the comparison may be meaningless, but “false” is not a good answer either, even though a Boolean is either true or false by definition and NotABool would be even more crazy. What a rabbit hole.
- Sean1708 9y agoWhat's the reasoning behind this particular example?
- uwu 9y agoi actually got it from https://wtfjs.com/ https://wtfjs.com/ which was linked in another comment someone explained how it works here: https://news.ycombinator.com/item?id=14891850 https://news.ycombinator.com/item?id=14891850
- twiss 9y agoTo those curious what it does, Object.create(Array) creates an object with the Array constructor function (not the Array prototype) as its prototype. The Array constructor function, like all functions, has a length property indicating the number of arguments it takes. That property is accessed through the created object's prototype chain. The Array constructor's length property is defined to be 1, referring to the fact that if you call it with 1 number, you get an array of that length filled with undefineds. If you call it with something else or another number of arguments, you get an array filled with the arguments.
- b0rsuk 9y ago$python Python 2.7.9 (default, Jun 29 2016, 13:08:31) [GCC 4.9.2] on linux2 >>> True + True 2 >>> okay... python3 Python 3.4.2 (default, Oct 8 2014, 10:45:20) [GCC 4.9.1] on linux Type "help", "copyright", "credits" or "license" for more information. >>> True + True 2 >>> I'm going to try this in Rust.
- Ygg2 9y ago> I'm going to try this in Rust. https://play.integer32.com/?gist=4c95f461e58727607c4b1c2c569af913&version=stable https://play.integer32.com/?gist=4c95f461e58727607c4b1c2c569... error[E0369]: binary operation `+` cannot be applied to type `bool` --> src/main.rs:5:13 | 5 | let x = true + true; | ^^^^^^^^^^^ | = note: an implementation of `std::ops::Add` might be missing for `bool`
- masklinn 9y ago> = note: an implementation of `std::ops::Add` might be missing for `bool` Incidentally you can not provide one, because implementing a trait on a type currently requires that either the trait or the type be local to the current crate: = note: the impl does not reference any types defined in this crate = note: define and implement a trait or new type instead
- akubera 9y agoWorks in C++: https://godbolt.org/g/bfM2zq https://godbolt.org/g/bfM2zq Does not compile in rust: https://godbolt.org/g/GTHM83 https://godbolt.org/g/GTHM83
- masklinn 9y agoI prefer `5 < {}` (fixed in Python 3).
- b0rsuk 9y agoI get the kick out of: True, False = False, True # fixed in Python3
- twiss 9y agoWe can fix this with Greater than or equal operator (>=): 3 > 2 >= 1 // true What? No, JavaScript doesn't have chained comparison operators, as the author seems to know but not explain. Overall this list is pretty misleading and uninteresting IMHO.
- sAbakumoff 9y agoIt's interesting to see that a lot of people make fun of JS, publish articles on how weird it could be, receive a ton of likes, but still it's the most popular programming language at the moment. It's like Stockholm Syndrome we developed with time!
- Ygg2 9y ago> It's like Stockholm Syndrome we developed with time! It's easy to use and widely available. Give me example of another computer language that is installed on every computer with internet access. The base language isn't that bad, it's just that some bad initial decisions and backwards compatibility forced some really sharp paper cuts, most of you can avoid. Does this means that One True JS Programmer can write flawless JS Code? No, but in practice you don't have to write flawless JS Code.
- sAbakumoff 9y agoI agree that most of "very strange things" about JS can be avoided. 90% of these "look, js is weird" articles are quite useless as they make use of very artificial scenarios.
- Ygg2 9y agoYeah, but overall, I think it's useful since it highlights some cornerstones in JS.
- b0rsuk 9y agoThese are merely extreme cases. Javascript is full of less mind-boggling inconveniences. It's not like they only kept the really bad features for laughs and fixed the rest.
- sAbakumoff 9y agoAgree. "this" thing in JS can be really inconvenient for beginners.
- 9y ago
- nthcolumn 9y agoFrom a few years back but made me laugh a lot: https://www.destroyallsoftware.com/talks/wat https://www.destroyallsoftware.com/talks/wat
- dennykane 9y ago<sarcasm>Haha... LOL... WTF... JS is such a silly scripting language, that ends up in such silly places (web pages, electron apps). I mean, its probably utterly impossible that it will revolutionize the world by taking general computation to the next level via some kind of, I dunno, next generation operating system, like https://linuxontheweb.org https://linuxontheweb.org !</sarcasm> Hi, I'm the creator of "Linux on the Web", the next evolution of general computation :)
- vmasto 9y ago> If you are a professional developer, you can consider these examples as a great resource for interview questions and quizzes for newcomers in your company No, do not consider these examples as a "great" resource for interview questions. They are nothing more than tricks and hacks abusing the bad aspects of the language and anyone who includes them in an interview has failed in screening JavaScript developers, at least in my book. A JS developer should understand that JavaScript has some flawed, unfixable core concepts and educate themselves on how to avoid them, not use them in actual production code or memorize every coercion scenario. Some simple rules: 1. Always use referential equality checks (triple equal `===`). In idiomatic JS you can also use double equality only when explicitly checking against undefined or null (foo == null). It's the only use of abstract equality that I find acceptable. 2. Learn how the `this` execution context works. Kyle Simpson explains it very well in YDKJS (https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md https://github.com/getify/You-Dont-Know-JS/blob/master/this%...). There are four simple rules that matter and are straightforward to grasp. 3. Familiarize yourself with how type coercion works in JS but avoid it. The spec is quite easy to follow in this matter and follows very specific, documented rules. e.g.: https://www.ecma-international.org/ecma-262/8.0/index.html#sec-additive-operators https://www.ecma-international.org/ecma-262/8.0/index.html#s... https://www.ecma-international.org/ecma-262/8.0/index.html#sec-abstract-equality-comparison https://www.ecma-international.org/ecma-262/8.0/index.html#s... Use strictly as reference. 4. Stop using plain ES5, the language currently is ES2017. ES2015 and beyond provide modern constructs that make most of ES5's weirdness obsolete. For example, never use `var` anymore, `const` and `let` are superior initializers. By following the above rules a JS developer should be fine in 99% of cases, in my experience. Yes, JavaScript will possibly implode on you on the rest 1%, but I'd be hard pressed to find a (similarly popular) language that doesn't. If one finds that to be unacceptable, enabling types via TypeScript or Flow should make their life even easier.
- aaron-lebo 9y ago1. Always use referential equality checks (triple equal `===`). In idiomatic JS you can also use double equality only when explicitly checking against undefined or null (foo == null). It's the only use of abstract equality that I find acceptable. I've found this advice in guides and in codebases, but it seems unnecessary to me. The vast majority of equality checks are of the if (str == 'str') or if (n == 0) type. It's rare that you are actually comparing two objects of different types and when you are it's kind of nice to see === and know, otherwise it's just kinda ugly (kinda like const in languages, but we don't gotta hash that out here). There is a debate like this in the lisp community over eql and such. Similarly, isn't (foo == null) redundant? In most cases if (!foo) is what you are interested in and it's cleaner. Is this incorrect? Would be cool to have it clarified. Have never actually run into a bug due to it, so not sure if the limitations of == are mitigated though coding style or what. But in total agreement otherwise. Modern JS is really good, it's as productive as anything else, expressive, and once you know the quirks they are easy to avoid. Where JS has problems is inexperienced devs where they can code with var and for (var ...) monstrosities that date back to like 1996.
- Tade0 9y agoFrom now on I'm going to include at least one of these in each interview I'll be conducting - for extra points of course. Anyway a lot of these examples can be explained if you know how type coercion works in JS and are aware what the `valueOf` method exists for. Here's a nice write-up about this mechanism: http://2ality.com/2011/12/fake-operator-overloading.html http://2ality.com/2011/12/fake-operator-overloading.html
- vmasto 9y ago> From now on I'm going to include at least one of these in each interview I'll be conducting - for extra points of course. There's absolutely 0 benefit from an engineering standpoint in having type coercion memorized in JavaScript. I'd personally immediately terminate every interview that posed such questions ({} + [] + '' or whatever). I mean no offense, but I'd ask you to reconsider. People who ask trick/puzzle questions and hacks in interviews do not understand (or haven't thought deeply enough) how to properly screen JS developers which eventually goes through to the team itself. There are at least a dozen more interesting topics to question on if you want to assign extra points than useless stuff that should never be into production in the first place.
- naugtur 9y agoYeah, sounds like a good way to get junior developers impressed and anyone with real experience to drop out from the interview.
- Tade0 9y ago> There's absolutely 0 benefit from an engineering standpoint in having type coercion memorized in JavaScript. I would argue there is one: tl;dr: Planning for the worst from the people who tend to generate code which is, in one word, bad but which they managed to push to production. === When you know you're going to work with people who are not familiar with this concept, but still managed to shoehorn some code that looks a lot like these examples. Recent case: A local front-end server for development purposes and an SPA with a login form. The server checks for certain, hard-coded credentials and if they match lets the user through. Problem was, if you didn't get them right at the first try the proper credentials stopped working until you reloaded the page. How did that happen? There's an extra field in the form that is initialized to an empty string, but if the form is reset(on login failure) it is set to null, while the server checks for: field == '', because somebody assumed this would be enough. Null is falsy, but it's not equal to other falsy values. People who don't know that are usually left scratching their heads. === Anyway no offense taken and I'd be happy to hear some suggestions on how I could improve this process. Usually when I ask a "trick" question I give a warning beforehand indicating, that this is not something which is going to affect their score negatively. I found that normally people like this part and are often curious about the proper answer. EDIT: One thing I would like to note is that I conduct interviews for the project which I'm currently in, so I'm going to suffer the consequences of any bad decisions on my part eventually.
- tomxor 9y agoExcept for "Precision of 0.1 + 0.2" which all programmers should know is a floating point fraction arithmetic limitation, not a JavaScript issue.
- ndz 9y agoThat's one of proofs that JavaScript is an evil without TypeScript especially in inexperienced hands :)
- LoSboccacc 9y agoNaN != NaN should be obvious, otherwise Math.sqrt(-1) == 0/0
- deelowe 9y agoSuch blatant misuse of the language in these examples. Not sure what to think. It seems like the author has a good understanding of JS, but then goes out of the way to purposefully misrepresent things to construct strawmen simply to then tear them down. If someone comes across this without being familiar with JS, they could very easily be misled. As a comparison, how many WTF C++ examples could be constructed if people misused arrays, pointers, bitwise comparators, oeprator overloads, templates, etc... to create nonsensical operations?
- pvg 9y agoThere is plenty of verbiage at the top explaining the motivation (some of it even under a big heading 'Motivation'). These aren't misrepresentations (let alone 'strawmen', whatever that might mean in this context) and there is no 'tearing down' at all, just links to explanations.
- b0rsuk 9y agoYou might trip on one of these misfeatures when a variable doesn't contain what you think it does. Or when you make a typo. In those cases, you're generally grateful for a strongly-typed language or a strict compiler.
- johnhenry 9y agoThis is really useful because of the attached explanations.
- gattilorenz 9y ago(typeof (new (class { class () {} }))) // -> 'object' It seems like we're declaring a class inside of class. Should be and error, however, we get an 'object' string. Explanation: Since ECMAScript 5 era, keywords are allowed as property names. Can anyone explain why allowing keywords as property names seemed a good idea? To me it creates a lot of potential for confusion without providing enough benefits, but I'd like to be... enlightened
- masklinn 9y agoBecause they found out they had little reason not to, and it can be convenient e.g. in Python when messing around with metaprogramming you have to use `cls` or `kls` or `klass` rather than the obvious `class` as a local variable name, just because keywords can't be used in other context. It's even more annoying in JS as e.g. a property named `class` is very common in DOM contexts.
- justinpombrio 9y agoMy favorite: x = "053" y = 50 z = "40" x > y // -> true y > z // -> true z > x // -> true
- toomanybeersies 9y agoTo be fair, that's the case in Ruby and C as well, and probably other languages. It's because 0 coerces it into an octal. I actually had a bug because of this a while ago at work.