The Two Pillars of JavaScript: Part 1: How to Escape the 7th Circle of Hell
medium.com
medium.com
He tells us, again and again, that it's best to avoid trying to emulate inheritance in JavaScript, because that often goes horribly wrong - in JavaScript. I'm not sure it's valid to extrapolate his experience to outside JS. I get the impression he's teaching us how to avoid problems that we wouldn't have (or less so) if we weren't saddled with JS.
His enthusiasm for JS, meanwhile, seems a little misplaced. A language riddled with many horrible gotchas that inspired Mr. Crockford to write a book on how to avoid them? Why should we need to tiptoe around the fact that "this" means different things in different contexts? The "prototypal functions that happen to contain data" idiom is refreshingly different and interesting, but does it really offer advantages not found in "conventional" OOP or FP?
JS commands a huge following. But as Elliott hints at the beginning, its popularity is not a matter of choice. Netscape saddled us with a legacy where the API of every browser is necessarily JS. JS is the best language for programming browsers simply because it's the only one. That it's not a universal favorite is evidenced by the many projects that offer a "cross compile to JS" option. The users of those products would rather code in a different language.
All that said, a disclaimer: Though I've read _The Good Parts_ and other JS books, I avoid JS, I barely know JS, I have next to no experience with it and I suck at programming in it. So the foregoing is an opinion not backed by a wealth of knowledge and experience. I submit it as a kernel for discussion, hopefully by more knowledgeable people.
I've been focussed primarily on JavaScript development for the past 6 years (before that I was full-stack in previous positions) with some of my time spent helping out with the other tiers. This article echoes all my thoughts and experiences developing large, complicated and slick web apps using pretty much every JavaScript framework under the sun.
As others have pointed out, you can run your arbitrary code from another language with a polyfill so no one is "stuck" with JavaScript. At this point, the ubiquity of JavaScript is not something anyone should be be-moaning as it is not a negative, only a plus.
It's a great language and I would urge you to learn more through direct experience (functionally and not OOP-style). It's an easily accessible language to teach aspiring programmers: we just need to teach them the functional way and forget the ludicrousness of deep inheritance applied via prototypical inheritance.
It doesn't require memorizing a huge number of language features in order to write the majority of your code. You don't need to know the nuances of equality by reference upfront, or details about OOP. You have your operators and basic control flow, and you can go to town with them & be quickly rewarded. As you get into more complex needs, the language doesn't get in your way for the most part. It still offers a mechanism of OOP via prototypical inheritance, and functions are first class citizens so you can pass them around and meet your functional programming needs.
JS is not without its flaws - however, it is the easiest major language to get people productive in without a programming background, and slowly bring them along at their own pace in order to build a solid foundation.
i don't think that this is a great article because there's a lot of bloat around the content to wade through and filter.
It has yet to even obtain Java-level "write once, debug everywhere". Most of the people talking about "isomorphic JS" and "JS is everywhere" use, and expect, a single javascript VM implementation (V8).
with the exception of jQuery: i appreciate your point, even within the same browser, different js engine versions have wildly different behaviour.
You can't solve the problems of using OOP in JS. JS is functional at its core. OOP style class inheritance is completely inappropriate, and bolting it onto JS was bad overall for the language as wandering off the functional style creates some confusion and now the language inherits the problems of class inheritance.
Separation and extensibility are the great things to get. Separation you get in function scopes. Extensibility isn't obvious, so they bolted on OOP. It can be achieved but you have to go deeper into the functional world and people started demonstrating class inheritance as the answer. Was unfortunate.
That's not trivial.
People are cross compiling to javascript as part of a build process though, so you're wrong that it hasn't taken off. Coffescript, Typescript, ClojureScript, Elm, etc.
https://github.com/jashkenas/coffeescript/wiki/list-of-langu...
Clojure itself barely registers in language popularity indexes -- much less Clojurescript.
That much is clear. Your comment is essentially based on hearsay and is far from accurate.
You really should learn Javascript, and listen to the original article.
The "two pillars" of prototypical inheritance and lambdas with closures are actually two extremely powerful foundations that are rarely found together in any language, let alone a language with such ubiquity.
It is actually a much better language than it gets credit for. If you don't like the prototypical inheritance; you may safely ignore it and treat JS as a first-class functional language. If you don't like first-class functions with closures, then treat JS as a beautiful object-oriented language. It is so flexible it's almost absurd.
Are there gotchas? Sure, perhaps more than would be ideal, and in order to have both of these pillars in the same language, some odd stuff does pop up. But if you actually use it for a while, you'll come to realize the balance is in its favor.
http://jsperf.com/object-create-vs-crockford-vs-jorge-vs-con...
Since he mentioned HTML5 games and trying to improve perfomance by avoiding the garbage collector, well, the above benchmarks are not the kind of thing you would want to compromise on either.
So please, next time you say that it's impossible to build anything big and reliable with this design because YOU or people you know ended up in a mess, think again whether the problem really comes from the language, or the people.
Deep inheritance trees, on the other hand, are difficult to use beautifully but yet are often portrayed as a first class design pattern which often ends up in mess. A priori designed inheritance trees without experience how such designs evolve in production are probably one of the biggest issues, I would imagine.
I think deep inheritance is an expert design tool that is easy to get wrong... therefore I kinda agree that the first advice "don't use it" is not misplaced but should be probably followed with "unless you really know you need it".
Since Javascript is a dynamic language it is easy for me to imagine deep inheritance trees will lead there to a terrible mess quickly since there is no static type system to enforce the design constraints.
So, put more simply, don't make an Animal class if you have a Cow and a Tree, or you might end up treating legs and trunks the same. It should be no surprise, then, that bad things happen.
This is not the fault of the concept of inheritance, it is a fault in your thought process and the resulting design.
Correct, me if I'm wrong, but using the constructor pattern (and new) in Javascript is the only real way to create an object that has a prototypal link to the constructor function's prototype. So what does this have to do with classical inheritance?
Whoa, that's fighting talk. Next we'll be doing big design up front and (god forbid) beginning with the end in mind.
That was tongue-in-cheek, only because everywhere I go these days I see people bowing down at the altar of refactoring, rather than doing a bit of planning and getting it right first time.
You are correct about emphasizing more planning up front, of course. If anything deserves bowing at an altar, it's designing before you write code.
Indeed. And the fire IS Javascript...
The beginning of the article reads like care instructions someone would leave for the person they hired to babysit their pet velociraptor. "Now, here are all the things you shouldn't do or else Rapty will literally rip your face off"
The nicest part of it is the built-in hash table type and the related syntactic sugar that everyone for whatever reasons insists on calling "object".
One thing that makes me freeze right up, though, is I hear they're adding classes and inheritance and that whole OO clusterfuck to what's a nice, trim little dynamic language.
Like the article, I think it's possible to write good code in JS as it is, by accepting what it is, rather than trying to force it to be an OO language, by emulation or extension.
People call it an object because that is what it is. If your code is using Javascript objects as general purpose hash tables with the normal syntactic sugar then your code is broken[1]. The correct way to use an object as a hash table involves a bunch of ugly extra syntax that makes it more verbose than hash tables in any other language I'm aware of.
[1] http://www.devthought.com/2012/01/18/an-object-is-not-a-hash...
Every programming language leaves you a flavor in your mouth, it can be bitter and sweet. I like the idea of having living object in the DOM, it feels a little bit like smalltalk from a distance. but the language itself? I prefer to run a neutral VM or a secure native client in the browser to run other languajes.
Let's say originally you have this.
// Run node to the end
for (; node.next != null; node = node.next);
doSomethingElse();
After a few months of team work on the same code, one day, somebody got careless with the "x" key in vim and deleted the semicolon after the for. // Run node to the end
for (; node.next != null; node = node.next)
doSomethingElse();
And your web page still works! It's just become mysteriously very slow, sometimes. Must be caused by the latest Chrome update.There're lots of other ways for a pile of JavaScript code to accumulate bugs like this over time without a strict standard in place to lint everything. e.g. people forgetting to add "var" before variable declaration because they've been writing Python as well, causing namespace leaks that DON'T seem to break anything at first.
If you team has a standard practice to always lint everything, always do data binding in a certain way, never modify the DOM directly (combined with the proper libraries), etc. Then, yea, maybe you can scale up your team and the code size without always fixing funny bugs that pop up only after the original mistake was made 6 months ago.
But, standardized development practice with JavaScript? hmm.... how many hotshot frameworks and major updates to hotshot frameworks have we seen in the past 2 years? Compared to that, people using inheritance carelessly is just a minor problem.
Not to detract from the subject at hand because you do have a point, but that sort of error is caught by patch reviews. Even on my own projects I review diffs before/after I commit them.
There're a lot more problems with JavaScript than that. It's not even the most important problem IMHO.
A person I used to work with liked to hate on js constantly. Then I looked at his code. He was trying to write js like it was java, because that was his background! If I wrote js like that, then I would hate it too.
If you don't know the fundamental concepts of a language, then you are clearly not in a position to take advantage of it's built in characteristics. Different languages have different "natural logical patterns" that take advantage of that languages design choices. By learning these patterns in one language, then when working in a different language if you get stuck you will have them available.
This article makes the point that you should avoid trying to do standard OOP in js, and I would generalize this idea as follows:
Every programming language has its own unique attributes, conventions, patterns, etc... when working in a new language, it's important to learn how to write in that language's style, instead of imposing a different languages style.
Simply put, prototypical methodology reflects the mutability of reality. Object-oriented methodology reflects a visualization of reality.