News for hackers. Stuff that matters.
Re:Future JavaScript: what is still missing? by munificent on Sunday January 27, 2019 @02:13PM (#19013237)
> I already have a hard enough time teaching programmers about prototypical inheritance without the language actively lying to them.

One way to look at it is that you could consider not teaching the underlying prototypal inheritance model at all. If students will rarely run into code that relies on it, it may be vestigial semantics.

Think of it like how people used to teach patterns in C for doing object-oriented programming. For example, you could have a struct whose first field was a pointer to a table of functions for the operations you could perform on the object. In other words, how to implement your own vtables from scratch.

When C++ came along, it was still useful to understand vtables sometimes, but it wasn't something every programmer needed to fully internalize. C++ let them program at a higher level of abstraction.

> And it feels like an odd move in that class based OOP isn't the zeitgeist it once was.

Citation needed. :) Two of the newest, fastest growing languages are class-based: Kotlin and Swift. I'm not aware of any new prototype-based language that has noticeable growth.

Prototypes are a neat idea, but I think the market has pretty clearly shown that classes are a better practical approach to OOP.

Re:Future JavaScript: what is still missing? by danShumway on Sunday January 27, 2019 @03:36PM (#19013641)
I'm skeptical that classes make prototypal inheritance safe to ignore, because they're not a perfect abstraction. Opinion me, classes in Javascript do not act like classes in other langagues.

In particular, I still run into usage of `call` and `apply` on a regular basis.

  class Foo {
     constructor () { this.foo = 0; }
     log () { return this.foo; }
   }

  (new Foo()).log.call({ foo: 2 });
I guess I can explain the above without prototype, but it's certainly weird behavior for a classical OOP language, and at the very least it's dancing around prototype-like behavior.

Or, much worse:

  class Bar { constructor () { return new Foo(); } }
And you can say, "how often is a student ever going to run into that case", but part of being a student is experimenting with code. If an abstraction only holds as long as you never do something weird, then it's probably not a very good abstraction. In that case it's worth asking, "is it good language design to have a feature give surprising results as soon as you do something that's even slightly off of the beaten path?"
Re:Future JavaScript: what is still missing? by scarface74 on Sunday January 27, 2019 @03:54PM (#19013721)
Well, in that case the abstraction of private methods isn’t good either because there are ways to bypass them in C++ by passing a function pointer or in C# via reflection.
Re:Future JavaScript: what is still missing? by danShumway on Sunday January 27, 2019 @04:18PM (#19013843)
Arguably, yes.

However, I would say there's some difference in severity between a surprising behavior that results from the intersection between two features, and a surprising behavior that results because the way a feature is described is literally inaccurate.

You can break Javascript classes without using any other feature of the language. You don't have to resort to something like Proxies, or overriding native prototypes. This is because it's not that other parts of Javascript provide escape hatches to get around behavior, it's that the class syntax itself does not cover the entirety of the prototype system it is trying to obscure.

It's not ideal to have any breakage in an abstraction, but some breaks are worse than others. To me, edge cases like this:

  let foo = function () { this.x = 5; }
  class Bar extends foo { //No error? But why?
    constructor () { super(); }
  }

  foo = function () { this.x = 7; }
  console.log((new Bar()).x); // 5, not 7 or undefined.
are on a whole nother level of leaky abstractions over even some of the worst parts of C#. To me, this is an edge case that nearly any reasonably imaginative student would likely find at some point using only very basic components of the Javascript language. And I have no idea how I would even begin to tackle explaining this without saying, "Okay, throw out everything I taught you about classes, here's how the language really works."
Re:Future JavaScript: what is still missing? by AgentME on Sunday January 27, 2019 @09:30PM (#19015036)
I don't know why prototypes have to be required for explaining those two examples. 1: You can call a function with a different `this` value. 2: A constructor can override its return value and return something else besides the new instance of its class.
Re:Future JavaScript: what is still missing? by danShumway on Sunday January 27, 2019 @10:08PM (#19015121)
> You can call a function with a different `this` value.

To understand what that means, you need to understand what `this` is in Javascript -- that classes don't actually bind methods to an instance. So we have this idea of methods from other languages that turn out to be kind of the wrong way of thinking about things.

From `this`, the obvious next question is, "so what's the difference between adding a method to a class and just attaching it to an object?" And it turns out that practically, the difference is very small -- and in fact it's very easy for us to remove or add methods to a class that look and act very similarly to the methods in a class descriptor. So what we're calling a "class" is no longer a descriptor or a set of laws about what an instance is and what it can do, it's just a blueprint of how to build an instance at runtime.

We haven't gotten rid of classes yet, but we're already working with something that feels foreign to a number of programmers coming out of traditional OOP languages. `this` means that what a traditional OOP programmer from Java thinks of as a "method" doesn't exist. It means that the context of a function is determined at runtime, not at compile time.

You don't need to use the word "prototype" to talk about that, but it's what I would call very prototype-ish behavior. Arguably, by the time someone understands `this`, they've already learned about half of what they need to know to grok prototypes anyway -- all that's left is to tell them that if a property isn't found on an object, there's a special property JS will traverse to look for it elsewhere. But sure, we can delay talking about that for right now.

> A constructor can override its return value and return something else besides the new instance of its class.

Constructors complicate things more. We already know from above that a class isn't really a descriptor of what an object can do, instead we're thinking about it like a blueprint that tells us how to create an object at runtime (this is also incorrect, but we're sticking with that definition because we don't want to use the word "prototype"). Now we find out we can override the return value of a constructor. The obvious question a good student will ask is, "why? What use-case is there for treating a constructor function like a normal function?"

Again, we don't have to jump to prototype from here, but we do kind of need to explain that the `new` keyword is actually doing most of the work when we build a class, and the reason we can do weird things with a constructor is because a constructor is just another function. But we'll avoid prototype by saying that `new` just makes an instance of a class, and that behavior can be overridden by returning another object from the constructor that `new` invokes.

And when the student figures out that they can call `new` on an anonymous function without returning anything and it still creates an object, we can delay talking about prototype even farther, because we'll just lie and say that pure functions are a shorthand for making classes that are only a constructor.

But increasingly the question becomes, why wouldn't we talk about prototype now? Ostensibly, the point of classes is that it hides all the weirdness of the prototype system. In my experience, people struggle with prototypes because they're not Java. But JS classes also aren't Java, or at least they stop being Java as soon as you do anything even mildly interesting with them. So if people who learn classes in depth still have to grapple with the fact that class definitions are constructed at runtime, and that instance methods can be modified after they're created, and that methods aren't inherently bound to instances at all, what have we gained?

Re:Future JavaScript: what is still missing? by AgentME on Monday January 28, 2019 @03:28AM (#19015984)
I agree that prototypes come into play if you start asking "why did they add this feature?" to either of those questions, or if you want to explain why JS behaves the way it does if you go off the paved path ("And when the student figures out that they can call `new` on an anonymous function without returning anything and it still creates an object..."). I think I disagree that either of those are on the critical path to becoming productive with a language.

I just think people really over-emphasize the difference between "class-based" and "prototype-based" languages as if they're completely different in how users code with them. In my experience, the primary interesting consequences of JS's prototype-basedness vs class-based languages is that you can call methods with arbitrary `this` values, monkey-patch classes at runtime, or even change the class of an object at runtime. In other languages, these kinds of features would be called reflection, they would be in a late chapter labeled "advanced features", and people wouldn't worry about teaching them to students before they had a good handle on the rest of the language.

Re:Future JavaScript: what is still missing? by zzo38computer on Sunday January 27, 2019 @06:28PM (#19014415)
I do not use the "class" command in JavaScript (although I know it just does prototype inheritance), and think it was unnecessary to add (but you can't really remove it now).

I think prototype inheritance is often more useful than class inheritance; I do not agree that classes are necessarily better. Prototype inheritance can be used for more kind of things (especially with Object.create and Object.getPrototypeOf; I sometimes use these).

Re:Future JavaScript: what is still missing? by agd621 on Sunday January 27, 2019 @02:54PM (#19013460)
I don’t disagree that prototype is rare in real world practice but, anecdotally, it has come up in ~20% of my interviews in some fashion. That’s enough that I would be upset if the person teaching me JavaScript didn’t also teach me prototypal inheritance.
Re:Future JavaScript: what is still missing? by thekaleb on Sunday January 27, 2019 @03:54PM (#19013727)
I only bring up the prototype to determine if I would classify the interviewee as a senior JavaScript developer or not.
Re:Future JavaScript: what is still missing? by bpicolo on Sunday January 27, 2019 @06:15PM (#19014370)
In modern times that's something you can easily throw far back in mindbank, because in practice using ES6 it almost never comes up, and it's super easy to do a quick refresher on the semantics. If I didn't know that interviewers tended to ask about it in frontend inteviews (because they totally do), would never bother to keep up to date with the semantics
Re:Future JavaScript: what is still missing? by adrianhel on Sunday January 27, 2019 @04:39PM (#19013943)
Object.defineProperty('senior', { value: true, enumerable: false })
Re:Future JavaScript: what is still missing? by scarface74 on Sunday January 27, 2019 @06:03PM (#19014304)
There are two things I would expect even a mid level developer to know - how prototypical inheritance works and how “this” works in JS.