Hacker News new | past | comments | ask | show | jobs | submit login
Introduction to Object-Oriented JavaScript (developer.mozilla.org)
96 points by Garbage on May 10, 2015 | hide | past | favorite | 62 comments



JS isn't OOP and it doesn't need to be. Please read this instead:

https://medium.com/javascript-scene/the-two-pillars-of-javas...


Smalltalk has always had lambdas in the form of block objects. It uses them everywhere and for everything, even implementing control flow constructs like if/then/else and while. It also uses them to implement Lisp-style higher-order iterators like mapcar (collect:), reduce (inject:into:), and remove-if-not (select:), which though possible in JavaScript (see Prototype.js), is generally uncommon because JavaScript's lambda syntax has historically been the most verbose of any dynamic language.

Anyone who claims lambdas are somehow new to or incompatible with OOP clearly doesn't understand OOP, since lambdas have been an integral part of the most influential pure OO language (Smalltalk) for 40 years.


I've also seen very simple object systems built purely using closures in Lisp. I can't remember where I've seen it, but it usually involves the bank account example. Since no other Lisp features were involved,until you start glossing over with macros, this could be replicated in JS. It'd look strange but it's certainly possible, e.g:

  var savings = account(200);

  savings('deposit')(200);
  console.log(savings('amount')); // should print 400

  savings('withdraw')(200);
  console.log(savings('amount')); // should print 200
If you can build an OO system in terms of lambdas and closures, does it mean the two are incompatible? I don't think so.




Though it does not have lexical scope / closures for 40 years.


If you're trying to say that OOP isn't the central organizing principle of JavaScript, then I 100% agree with you. Lambdas and closures are awesome.

However, JavaScript does have the "new" keyword, and I would argue that constructors are quite central to JavaScript and good idiomatic JavaScript uses them. And it exposes YourConstructor.prototype, which I would argue is also useful.

So I guess maybe you're saying something about the term OOP that I don't understand. Maybe OOP means "everything is an object" to you? Or it means multiple inheritance?

I guess I don't understand the distinction you're trying to draw when you say "not OOP".


There's a whole depth of abstractions that people imply when they talk about OOP in JavaScript. In my mind they go something like this.

    1) Using object literals for values.
    2) Using object literals with functions.
    3) Using object literals with functions and calling them in contexts (`this`, `bind`, `apply`).
    4) Using the `new` keyword.
    5) Designing objects with inheritance hierarchies or prototype chains.
    6) Designing mutable and stateful objects with indefinite life spans.
I don't understand the arguments that classical-ish inheritance in JS is bad while prototypical inheritance is somehow better. I've worked in codebases that liberally extend objects into different types of objects with long prototype chains, and IMHO they suffered from the same problems that people complain about in classical inheritance: tight coupling, premature/wrong abstractions, gradual violations of open/closed, etc.

Personally, I go through 1-4 liberally and 5 and 6 conservatively. IMHO, complaints about inheritance mechanisms seem to have something in common with the people who talk about the special needs of "large-scale applications". Why not just make smaller apps, or make smaller things that compose with less knowledge of where they are?

NB: It's entirely possible that I haven't run into the kind of complex requirements where liberal inheritance is a good fit. I'd be interested in hearing stories about when that worked out well.


> Why not just make smaller apps, or make smaller things that compose with less knowledge of where they are?

The easy answer to this is that successful apps have a tendency to grow larger than expected and splitting them up requires care and lots of work. Class based inheritance provides a familiar way to split up the state space via encapsulation. It provides some boundaries instead of none and theoretically allows you to separate out your concerns and not have to think about the system-wide implications when writing code in your class.

I'm in the functional camp and think classes aren't a great way to build software but I support the addition of `class` to ES6 since it shifts the ecosystem from a hundred slightly-incompatible versions to a single one. The mystery to me is why the people who advocate for JS classes are still writing JS rather than writing Typescript or Dart to further constrain their state space with a type system.


Article of the same author, on the related subject: https://medium.com/javascript-scene/how-to-fix-the-es6-class...


I agree. JS is beautiful in the parts where it encourages functional, not object, programming. That link puts it nicely: "You're working in the phony version of JavaScript that only exists to dress the language up like Java." In the Mozilla article, I can hardly believe I'm reading discredited perennials like "OOP promotes greater flexibility and maintainability in programming ... Because OOP strongly emphasizes modularity, object-oriented code is simpler to develop and easier to understand later on." That was the promise, in 1985. The reality is, OOP has created a snarl of programs where mutable state is the defining characteristic, justified by a consulting industry that is more promotion than real, grounded theory. They live on.


You're vastly overstating what you consider the "reality" of object oriented programming. Systems designed to be OO from the beginning are clearly massively successful at producing incredibly complicated software. The paradigm has not been discredited despite your assertion or your personal idea of beauty.


Nice try, Grady.

(edit... y'all, please let me have a little joke)


Nope, I knew there'd be a regular humorless hn down voting dickhead. Oh right, I'm not supposed to mention that, or I'll get more dread down votes lol.


So have procedural and functional systems. What is your point? There's no practical evidence that those projects were successful because of OOP, and there's no theoretical basis for believing it either. In the meantime, object-oriented programming languages require one to make some pretty uncomfortable tradeoffs (for example, it makes type inference undecidable and practically requires virtual dispatch), so even if they are just a noop, we should still avoid it whenever possible.


My point, which I felt i made clearly, is that the OP overstated the discrediting of object oriented programming. I'm not sure what you are replying to, but not a single sentence in your post addresses that at all, so I'm not going to bother to address any of your points. They are all tangential.


Then your assertion was also tangential, as whether or not people have been successful at producing complicated software with OOP has very little to do with whether or not it has been discredited. People have been very successful at producing complex software that uses goto, but goto has been discredited. This is not because people thought that goto made it impossible to produce complex software, but because people thought that goto did not promote local reasoning well, which is similar to my objections to OOP.

Either way, my point was that there are many other paradigms that have been equally successful; that suggests that we should be looking at its other objective downsides in determining whether or not to add it to a programming language, rather than simply assume that it should be there.


The promise in 1985 was Smalltalk; the reality was Java. Your argument rests on an industry bait-and-switch.


No, the reality is not just Java. It's Ruby, C#, Objective-C, Python, etc. Other languages have made object systems that aren't as ugly as Java's


How about games? I feel OOP makes the most sense when coding games. You want mutable objects (for example enemies) behaving the same.


It's awful in games too, although the grain of OO languages makes it a little more compelling at first. OO encourages slicing up code into black boxes, and it just doesn't work.

What a game needs is a database view of the world - not a strict formalized model like SQL, but a customized, mixed-paradigm mode of keeping a ton of global state organized. Game actors are not truly independent, they're a view on various fragments of data allocated semi-independently and late bound into some association. They're all part of one world.


You're exactly right. The problem with OO is that you are really making state changes in what you should think of as an in-memory database, but the languages offer you no support for doing so logically. A logical language, or as you suggest, a mixed-paradigm language, could give you some logical assistance in enforcing consistent state transitions. In OO languages, you have to enforce all the logical constraints yourself, in code. And you get so used to it, you begin to think that's the way it's done, and you embed the knowledge in your Patterns book.


This article needs some code examples. Read it through and still not sure how to do this.


This is just in time. I just read a chapter in a JavaScript book about OO programming in JS and finished the chapter very confused. It demonstrated about 12 different patterns people have used for creating 'classes' and 'subclassing' them, each with a list of advantages and disadvantages.

Eg there's the 'parasitic instantiation' and then there's the 'Constructor pattern' and then there's the 'Parasitic Constructor', and there's like 3 other patterns that have their own permutations. Coming from Python and then Java, where classes just work...it's kind of annoying.

[edit] I was being a bit hyperbolic, the book discussed 6 ways of inheritance in JS, those being (1) Prototype Chaining (2) Constructor Stealing (3) Combination Inheritance <- most popular one according to the book (4) Prototypal Inheritance (5) Parasitic Inheritance (6) Parasitic Combination Inheritance <- pattern that is generally the best according to the book


Inheritance is rarely necessary


When will people start releasing ES6 editions of things? Seems so old school when you can simply write

`class Foo extends Bar {}`


Now you're being old school. It's called ES2015 now! ;)

(edit: app I was using chopped my comment...)


True true, though it's more characters to type :) And is ES7 going to be called ES2016? (Considering how JavaScript is starting to run everything there is a certain long-term logic to this naming approach.)


ES7 is still ES7, and ES8 is still ES8. I'm not even convinced ES6 got renamed - nowhere apart from HN comments have I seen it called ES2015.


I'm still worried that the idea of a namespace is still being thrown around in JavaScript. If you've used PHP (which presumably quite a few inexperienced programmers might have before they get into JavaScript), JavaScript namespaces act nothing like PHP namespaces. A JavaScript namespace is just a global variable. Nothing fancy.


But why? JavaScript obviously wasn't made with object-orientation in mind.


That's why every framework invents its own kind of OO for it. :-(


> Or we can set this explicitly using Function#call (or Function#apply), as shown at the end of the example.

Or we can define a variable self in the class, set self = this in the constructor, and refer or that hereon.


Wouldnt the only thing that js need to be fully oo be a proper inheritence? Prototyping has its advantages too though


Inheritance is no fundamental property of OO systems, and JavaScript has always supported it anyway (it just did not provide syntactic sugar).

JavaScript always has been an object-oriented language - arguably just not a partcularly well-designed one, and not a pure one (as not all computation happens through message passing).


That's coming in es6


I know people are crying out for this, but I can only shudder inside at the unholy mudball messes that will result. Inheritance is one of those things we shouldn't let anyone use until they're 40 or so.


Or, with great power comes great responsibility, and we shouldn't let uneducated and untrained quick-buck "developers" work on our software.


Inheritance is barely ever necessary, or even important, for any software problem, real or imagined.


Well to be fair to myself, I was mainly making a joke. But the simple truth is that inheritance doesn't bring new power to the table, just syntax sugar, and with great sugar comes diabetes and painful death.


Classes is a big enough portion of sugar to change expression level of code. After writing ES6 few months I don't like to write ES5 again, when I have to, and there is a lot of people who think so. Arrow functions is the another (if not first) big thing which makes this feeling stronger, and it's just a syntax sugar also. OO in ES5 looks less readable and less.. "native" than in ES6. Hope in some ES version 'this' insanity will be fixed and all will be just fine with classes.

just for note: I have never used "extends" in ES6.


im rly in love with typescript right now, looking forward to es6!


I just had my first exposure to Typescript recently, and the only part I liked was the fact that it allowed me to mix in plain old, untyped js syntax. TS, used as TS, feels verbose, like java, with lots of extra keyboard-typing to create a simple program.


>with lots of extra keyboard-typing to create a simple program.

When people say this as a knock against a language I can't help but wonder how they got so far in their careers using only two fingers.

Now, if you want to say that verbosity obscures intent and expressivity, then that's a fine argument to make (you'll have an steep hill to climb to show that types are an instance of this however). But if your development is bottlenecked by your typing speed, there's something seriously wrong.


It's both. I'm a poor typist, and more importantly, the terser the better. The less screen noise you have to filter, the clearer the picture becomes. I also put high value on DRY.


With optionally typed languages like Dart and TypeScript, you only have to add types to things like fields and functions/methods to get all the tooling benefits. Type inference takes care of the rest.

Secondly, you should be able to auto-complete pretty much everything.


"you should be able to auto-complete pretty much everything"

Requires tooling.


Eh.. grep is also a tool? Every function you write is a tool. The whole industry is built on tools and tools that make tools..


Sure. But programming languages whose claim to utility lies in an IDE -- they aren't necessarily bad, but it's not a programming language you're selling me, it's a whole environment: MS Visual Studio or whatever. A complex language requires lots of tooling like that, and a simple language doesn't. I have never missed autocompletion in Javascript, but I cannot function without IDE support in Scala. We're off the topic of OO in Javascript, but I wanted to make the point that I don't automatically consider that "IDEs can autocomplete" is a positive feature -- if you need autocomplete, that's a problem.


> but it's not a programming language you're selling me, it's a whole environment

Well, yes, because programming languages don't exist in a vacuum. The currently available libraries, tools, and documentation are very important if you decide to actually do something with that language.

> I have never missed autocompletion in Javascript

A moment ago, you complained about having to press a few more keys for the type annotations.

> I wanted to make the point that I don't automatically consider that "IDEs can autocomplete" is a positive feature

That there are IDEs which let you auto-complete everything is a positive feature.

Being toolable doesn't mean that those tools exist. If those tools exist, you can make use of them if you decide to use this language. This is a good thing.

By the way, JavaScript doesn't lack good tooling because it doesn't need good tooling. It's the way it is, because offering good tooling for JavaScript is really difficult. ES6's modules and classes will help with that though. The tools will make good use of this statically available information.


>> I have never missed autocompletion in Javascript

>A moment ago, you complained about having to press a few more keys for the type annotations."

For Typescript, I dislike the extra typing. I have never missed autocompletion in Javascript. Where is the contradiction?


One would think that 20 additional characters per function don't really matter if you can save 100 keystrokes.

Compared to JavaScript, I have to press fewer keys when I write Dart. (This would be also true without shorthands like method cascades.)


What's with this luddite mentality that pervades some areas of software? This meme that epitomizes terminal-based, mouseless, IDE-less development is just seriously absurd. We of all people should embrace modern tools that make development more productive. Tooling is the future, we should be pushing the envelope not romanticizing the past.


As I explained, requiring an IDE to make effective use of a language is a marker for a complex language. The system as a whole may be an effective way to build programs for some people, but it's now more than a language. The logical extreme is visual programming which reappears every few years. After a while, most people rediscover that languages articulate concepts better than visual metaphors. IDEs aren't as extreme, but sometimes don't merely enhance editing the language, but become almost a required part of the language. I am sure Martin Odersky can write Scala programs in Notepad, but I myself cannot write a Scala program without mouse hovers explaining the inferred type of my variable. It's an effective total programming system, but as a pure language, it's so complex I can only program it in a certain environment.


But why is environment flexibility a requirement? When are you genuinely constrained to use, say, only a terminal? I can think of no situation where this is true by necessity (rather than artificial constraint).


Well, first of all, I am not against IDEs. I use one most days of the week, and I'm productive in it. Some of the above discussion has misinterpreted my remarks. I only ever said, that a language making itself amenable to IDEs isn't a convincer for me, since languages requiring tooling to be effective are possibly less good as languages. So when somebody tells me Typescript is good because IDEs can autocomplete it, it's an unconvincing argument to me, since I prefer JavaScript which, having no type annotations, has less typing and little need for autocomplete in the first place.

I didn't even bring up environment flexibility, or terminals!

Since you asked, though, it is fairly nice to be able to ssh in to a box and make a code change, and recompile, for those languages that require that. Continuing with Scala as an example, I, myself, could not edit a Scala program extensively without benefit of an IDE. So say I have a Scala program sitting on a dev server where I'm building a batch image processing program. If Scala were as simple as Jacascript, I could easily use vi or emacs to iterate the development remotely. As it is, I edit and test locally on my laptop using an IDE, then push this big jar over to the server. So, there are plenty of cases where remote edit, compile, test cycle using a terminal is convenient.


And by the way, hackinthebochs, your line of argument down through this whole thread has been to call me a two fingered typist (accurate) with whom something is seriously wrong; a Luddite; and you erect straw man arguments like this, as if I'd somewhere argued for the environmental flexibility of terminals.


Certainly there was some extrapolation on my part (though I do find it amusing that I got the two-fingered part right). I was using your posts mainly as a jumping off point for discussion seeing as they seemed to be in the spirit of the mentality I was referring to.

The fact is we are being constrained by the past. We still program in plain text files, using languages and environments that are as basic as possible presumably to maximize flexibility of development. I don't see the point. There are those that eschew the mouse, or GUIs because the terminal is cool (or something). The fact is that this field is moving towards more and more tooling, hopefully improved visualization, and soon to be automation (imagine APIs automatically wiring themselves up, or the gruntwork drudgery of programming happening automatically). This is the future we should all be looking forward to, not placing arbitrary constraints on the languages and environments we use for the purpose of compatibility with outdated tools. The more constraints we place on ourselves, the longer this future will take to become reality.


I do appreciate the type inference.


I don't know about you but my experience with Java required me to type either the same or less than JS if we are comparing apple vs apple, not simple front end vs complicated back end.


Are you counting Java IDE keystrokes or actual number of characters on the screen? If it's the latter, I'd be interested in seeing an example since it's very much against the wisdom of the crowds here.

My experience is that the complicated part web app is the part that does the state coordination, which can be either end.


Java IDE of course. Not the number of characters on the screen.




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: