Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECMAScript editors: JS classes are not fake #836

Open
Jeff-Mott-OR opened this issue Aug 12, 2016 · 17 comments
Open

ECMAScript editors: JS classes are not fake #836

Jeff-Mott-OR opened this issue Aug 12, 2016 · 17 comments

Comments

@Jeff-Mott-OR
Copy link

Jeff-Mott-OR commented Aug 12, 2016

But does that mean JavaScript actually has classes? Plain and simple: No. ... the classes you have in other languages are not like the "classes" you're faking in JS.

At least a couple ECMAScript editors, Brian Terlson and Allen Wirfs-Brock, have implied or explicitly stated that the notion that JS classes are "fake" is incorrect.

Terlson explicitly said as much on reddit:

"it is not at all helpful for beginners to constantly be exposed to the notion that JS classes are "fake". They are not, they have real syntax and real semantics" (https://www.reddit.com/r/javascript/comments/4bmiqj/using_classes_in_javascript_es6_best_practice/d1avktu)

"There is no gold standard for "class". From a developer's perspective, a "class" is an OO encapsulation mechanism that involves creating methods, defining fields, and producing instances and has some sort of inheritance scheme. Making the definition of "class" more constrained than this is not only incorrect but also not a useful distinction to make at all." (https://www.reddit.com/r/javascript/comments/4bmiqj/using_classes_in_javascript_es6_best_practice/d1atm1a)

And Wirfs-Brock implied the same on twitter:

"What word do you use for “an open set of objects that share a common interface and implementation”?" (https://twitter.com/awbjs/status/689506114807857152)

Wirfs-Brock also gave a talk showing how Smalltalk's class model and JavaScript's constructor pattern are "exactly the same, basically." (https://www.youtube.com/watch?v=EPHmm8JiGbg&t=37m28s)

Likewise, Python's and Ruby's class and inheritance models are strikingly similar as well. In both languages, a class is a memory consuming runtime object, and inheritance happens by delegation.

If we were to pick a definition of "class" that accommodates not just Java/C#/C++ but also Smalltalk/Python/Ruby, then it would probably have to be something very much like Wirfs-Brock's tweet: A class is a descriptor for an open set of objects that share a common interface and implementation.

And if we accept that as the definition of class, then we have to acknowledge that JS classes are not fake. JS has real classes just like Smalltalk/Python/Ruby have real classes.

@getify
Copy link
Owner

getify commented Aug 12, 2016

I'm well aware of their opinions and I've debated both of those fine gentleman on many occasions. They're very smart and I respect them very much, but I think they're misguided on this point.

I stand by my assertion because the definition of "class" that most people have when they arrive at JS is shaped most strongly by Java and C++, mostly because academia still to this day prefers those languages in CS curriculums, just as it did 15-20 years ago when I went through it.

There's lots of opinions on what a class is or is not, and I've chosen mine and clearly stated it. I base that on both my own CS background, my own experience in C++ and Java, and the observation that many, many developers have taken similar paths to arrive at JS and found subsequent confusion (as evidenced by myriad posts on sites like SO).

The point I'm making is that the definition of class is less based on some academic principle and more on the common paths and experiences people have with it. I understand others have come through different paths, but this path I've taken and based my writings on is what works for me.

@Jeff-Mott-OR
Copy link
Author

An alternative that might make everyone happy is rather than focus on real vs fake, you could instead say that JavaScript's classes are different than Java/C++ but similar to Python/Ruby. Then go on to explain the under-the-hood details. That way you can still acknowledge and address the common paths and experiences but without the controversy of treating any implementation that's different from Java as fake.

@getify
Copy link
Owner

getify commented Aug 12, 2016

I can understand why "fake" ruffles feathers. I will perhaps think of a different term to create the contrast.

@getify
Copy link
Owner

getify commented Aug 12, 2016

Just want to point out, for posterity sake, that nearly 100% of anyone I ever teach about "class" and "inheritance" find the notion of "retroactive inheritance" -- the idea that changing a "class" after instantiation has the retroactive effect on the instance -- strange and bizarre. The fact that you can do that in JS (and I guess in python/ruby, though I don't know those langs at all) is where the strong feelings of "that's not a class!" come from.

JS has a long rich history of being able to mutate objects and do all sorts of dynamic borrowing/sharing of method behavior. ES6 class came along and said "stop doing that" and "be static just like Java and C++ are".

I still feel a class that can create retroactive inheritance is a strange, unnatural -- ahem fake -- class. And the fact is, that's how JS's object system works. If you remove the ability to dynamically mutate objects, I think you remove one of the most important parts of the heart of JS.

@Jeff-Mott-OR
Copy link
Author

...and I guess in python/ruby...

Yep. Couple minimal repl demos if you're curious.
Python: https://repl.it/CmeW/0
Ruby: https://repl.it/CmeX/0

If you remove the ability to dynamically mutate objects, I think you remove one of the most important parts of the heart of JS.

But... the class syntax didn't remove that ability. Right? We can still monkey patch (dynamically mutate), or borrow methods from, a class's prototype same as we could a constructor function's prototype.

@getify
Copy link
Owner

getify commented Aug 13, 2016

There's several caveats to that tho, like for instance the fact that super is statically bound and not dynamic like this. Eyes start glazing over in my workshops when I start explaining stuff like that. My conclusion is they want you to embrace static inheritance fully if you use the class keyword.

@Jeff-Mott-OR
Copy link
Author

Weren't our super calls always statically bound? Even long before ES6?

var P = {
    foo: function() { console.log( "P.foo" ); }
}

var C = {
    foo: function() {
        // super();
        P.foo.call(this);
    }
}

// Link C to P for delegation
Object.setPrototypeOf( C, P );

var c1 = Object.create(C);
c1.foo(); // "P.foo"

var D = {
    foo: function() { console.log( "D.foo" ); }
};

var E = {
    foo: C.foo
};

// Link E to D for delegation
Object.setPrototypeOf( E, D );

E.foo(); // "P.foo"

Even in the pre-ES6 days, borrowing methods that make some kind of super call was still just as problematic.

@raganwald
Copy link

raganwald commented Aug 13, 2016

@Jeff-Mott-OR:

With respect to your argument that YDKJS is wrong to claim that JavaScript only has “fake classes,” and that smart people disagree with the book, I wish to disagree that the book is wrong to make such an “opinionated” claim, and furthermore to argue that it is valuable to stake out such a contrarian position.

Let me start with this quote of yours

An alternative that might make everyone happy is...

Right there is the issue with this thread. A book is not an exercise in making everybody happy. Down that road lies pablum, everything boiled and blended until it is bland and ultimately, neither appetizing nor informative.

There are hundreds or even thousands of books about a popular language like JavaScript. Every book (or series of books) must stake out some kind of unique territory to be worth investing the time to read it, much less money to buy it.

By the nature of the beast, the more unique it is, the greater the likelihood that it will differ in some substantial way from the perspective of some other author or person. So the fact that a book is not all things to all people is not a disadvantage, it’s practically a requirement to be worth reading.

Given this idea of a book needing to be original and therefore to stake out a unique position on worthwhile matters (which you may choose to reject), the question becomes whether the way in which it stakes out its own territory is a benefit or a hazard.

I happen to write about “classes” in a way that is very different than YDKJS, but at the same time, I also think that the take-no-prisoners JavaScript-does-not have-real-classes perspective has enough meat on the bones to be informative.

If you reject it outright and say, “Well, these smart people disagree,” I think you are the poorer for that. I suggest you are better off saying, “Well, that is interesting, this author rejects something that appears at first glance to be a central pillar of the way these smart people describe the language. What’s up with that?”

Honestly, I can make a number of arguments in favour of saying that JavaScript doesn’t even fake classes, it doesn’t have them at all, not real, not fake. I can argue that the JS approach of “The word ‘class’ means whatever anybody feels like it means” waters down the word “class” to be practically useless for thinking and reasoning.

But this is YDKJS, and it makes its own excellent arguments. What is good about this series of books is that it is internally consistent: Its arguments about classes fit neatly with its arguments about everything else, so in sum it presents a coherent and useful model for thinking about JavaScript and using JavaScript. One can read the books and still use “classes” whether fake or bullshit or watered-down, one just thinks of them in a different way.

Or one can move along and decide to embrace what JavaScript calls classes in its pop culture way, and think, “Well, JS has classes, but I learned a lot from taking the time to understand the YDKJS perspective.”

Either way, I believe that this series of books should stay the course on its opinions about classes. It is not an official reference book. It does not purport to present the OneTrueWay:tm: to write programs. It promises that there are things we dont know about JavaScript, and that it will tell us these things, and that when we have learned them, we will be better programmers.

I think this is true of the series in general, and I claim this is true of its opinionated statement that JavaScript has fake classes. Even if you move along and decide to believe something else, I claim that you learn something you didn’t know by putting that disagreement aside and following YDKJS’s reasoning long enough to understand it.

@jpstone
Copy link

jpstone commented Oct 6, 2016

Of course they're fake. The new operator has been in use to instantiate "classes". But new doesn't return a new instance of the class...it returns a reference! Classes, such as in Java, just hold a contract and when new is called on them, a brand new object is created, not a reference.

So basically, the one operator we have had for years to use Javascript "classes"--new-- is entirely fake and misleading.

@getify
Copy link
Owner

getify commented Oct 7, 2016

Well... new does create a new object... and all objects are held by reference. So I don't understand that line of reasoning at all. This object is not an instance of a class though. It's just linked to another object.

@jpstone
Copy link

jpstone commented Oct 7, 2016

I never said it doesn't return a new object. I said it doesn't instantiate a new instance of the class. All of the "class" properties are really just a reference to the .prototype of the function.

@duckisland
Copy link

Acceptable to say fakery but not fake?
C'mon folks ECMAScript is about functional programming and DOM manipulation.

MDN states: "JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance."
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

Embrace the advantages of Functional Programming and reap the benefits. Hold on to OOP paradigms and miss the whole point. Chaining, streams, mapping, functors, monads and more await!

@theScottyJam
Copy link

theScottyJam commented Feb 18, 2022

I would like to add a couple of thoughts to this discussion.

@getify, earlier, stated that JavaScript doesn't have classes similar to Java, C#, or C++, and he expects that's where most people's background will come from. He later acknowledges that they may be more similar to Python's, Ruby's, or SmallTalk's classes.

I want to point something out here. Do we notice anything that's similar about the languages which have "real classes" and the languages which have "fake classes"? All of the "real class" containing languages are statically typed and rigid languages, while the "fake classes" languages are highly flexible and dynamic languages. This book argues that the reason JavaScript classes are so weird and different from that of C++/C#/Java is because it's built on prototypal inheritance, but I think the real reason is simply because JavaScript is such a dynamic language. If JavaScript was a bit less lenient in what it let you do at runtime, then their class syntax would behave a lot more like C++/C/Java class syntax (and less like Python/Ruby/SmallTalk's).

In the article, the following was stated

In general, faking classes in JS often sets more landmines for future coding than solving present real problems.

If this were really true, I would expect people in the Python/Ruby/SmallTalk communities to also be running around, yelling "Stop using our classes, they're fake, and will cause more harm than good!" But no, everyone seems to be content using class syntax over there, so why is JavaScript's class syntax so bad?

To be honest, I think the real problem with class syntax is the fact that JavaScript's existing object system is already so good and powerful, that many of us looked at this new feature and thought to ourselves "why would I use that". In an attempt to figure out why we disliked it, we started pointing fingers at the obvious difference, "it's built on prototypes, so it can't be real". But, perhaps all that's really going on is that we just don't need the classes as much as we might in other languages, there's nothing wrong with them, we just don't need them. That's at least my current working theory :).

A couple more things to add

There's lots of opinions on what a class is or is not, and I've chosen mine and clearly stated it. I base that on both my own CS background, my own experience in C++ and Java, and the observation that many, many developers have taken similar paths to arrive at JS and found subsequent confusion

My original language was Python, which perhaps is part of the reason I have my point of view on this matter. I've also noticed that more and more schools are starting to adopt Python as their programming language of choice for their entrance class, so over time, more and more people are going to be reading this article with a mindset similar to mind, and a different picture of what a class can and can not be.

The point I'm making is that the definition of class is less based on some academic principle and more on the common paths and experiences people have with it. I understand others have come through different paths, but this path I've taken and based my writings on is what works for me.

Ok, sure. But try also saying in your article next book that you believe JavaScript classes are fake, just as fake as classes from Python, Ruby, and SmallTalk, and see how that gets received. I don't think you can say that classes from the original OOP language are fake and walk away from that unscathed :). But, I do get the desire to exclude smallTalk whenever talking about OOP, because of how OOP has evolved. Still though, it's much easier to state that JavaScript doesn't have classes (because many from the community will agree with this) than it is to say that Python doesn't have classes, because no one is out there saying that. And yet, all of the arguments around JavaScript classes go against Python ones as well.

If you want to say that JavaScript classes are implemented differently than Java/C#/C++ classes, that's fine. You could even state that someone may have some unexpected surprises when using them. But I don't think it's fair to define "class" to be exactly how these three languages implement them, then act all surprised when a language that isn't one of these three has some differences in how they implement classes.

(Also, if anyone's interested, I have previously written an article on this subject, and had referenced this book. Just now, I had decided to see if there had been any conversations in the issues about this particular part of the book, which is how I found this topic).

Edit: Also, sorry, reading back through this I realize I used a bit of a harsher tone than I had meant to. Just know I was simply trying to express an opposing opinion, my intention wasn't to attack.

@getify
Copy link
Owner

getify commented Feb 18, 2022

But try also saying in your article

This isn't an article or blog post. It's not an evergreen reference encyclopedia on JS that gets updated weekly or monthly.

It's a book. It was written almost 8 years ago. It was published by O'Reilly. It was filed with the Library of Congess (or whatever that's called). It has been distributed in ebook form and printed on real paper, many thousands of times, distributed all over the world.


Moreover, the second edition of this book is underway (2 chapter drafts posted so far). Notably, the book title in this new edition is "Objects & Classes". I invite all of you to follow along as I write it, and if you have feedback during the writing, I'm happy to hear it (even if I don't change!).

You can expect an updated/refreshed perspective on all these topics, hopefully as or more useful than the first edition. JS has changed a lot in the last 8 years, as have I.

But it's also a guarantee that some of you are going to disagree with me on some of what I say. I hope the books can be respected for their merit even despite these reasonable differences in opinion/perspective.

@theScottyJam
Copy link

theScottyJam commented Feb 18, 2022

Haha, sorry, I edited that out. I've got a bad habit of posting something, then continuously editing it, because I don't like how I phrased something :p.

And, don't get me wrong, I think the book is an amazing book, you've dived into tons of depth about these different topics, and I think you've done a great job at it as well, and I look forward to see what the next edition holds, especially if it has some opinions that challenge mine.

Edit: JK, I thought that was quoting something I edited out. I've edited it now.

@theScottyJam
Copy link

Could you link me to your working draft of your next book edition? Now you've got my interest, and I would like to see what you've got.

@getify
Copy link
Owner

getify commented Feb 18, 2022

It's all right here on this repo. The 2nd edition has its own branch (and is indeed the default branch of this repo), and the first two completed books (published 2 years ago) are there, as well as the early draft work on this third book:

https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/objects-classes/README.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Second Edition
this & Object Prototypes
Development

No branches or pull requests

6 participants