News for hackers. Stuff that matters.
Re:Deep JavaScript by shp0ngle on Thursday June 10, 2021 @10:10AM (#27460979)
This is a bit off-topic

But I never understood prototypes and prototype inheritance, and how does that "map" to "classic" inheritance, from Java or C++. And I worked in FE for about 10 years...

It seems you can model "classic" inheritance using prototypes, but... there is something more there that I don't understand. I started using ES6 "class" as quickly as I could, but I still wish I understood what .prototype and .__proto__ is and how to use it. I feel like I "miss" a lot of JS when misunderstanding prototypes.

But none of my colleagues know either, so I guess I at least know what I don't know.

Re:Deep JavaScript by todd8 on Thursday June 10, 2021 @12:12PM (#27462352)
Around 30 years ago (five years before advent of Javascript), I built a successful company around a distributed network programming framework that used prototype based objects. Objects in object oriented systems usually share some behavior via common methods, and they share some structure for their data members; the methods and structure are described by the object's class. Classes are language constructs with their own complex behaviors.

A class is like a blueprint used by the language compiler and runtime to build (allocate) objects. In languages like Python, Ruby, Smalltalk, or Common Lisp these classes are present in some form at runtime controlling the memory allocation of objects, the initialization of member fields, the dispatching of generic or virtual functions and so forth. Since the classes are present in some shadowy form at runtime, they themselves have behaviors controlled by meta-classes which in some languages can be manipulated at runtime (e.g. monkey-patching).

Prototype based object systems don't use classes to accomplish this sharing of behavior and structure. Such systems have a conceptually simpler set of primitives to accomplish the sharing and classes aren't needed. In prototype based systems one can clone an existing object, even an empty object. After cloning an object one can add fields to the object.

Structural sharing is easy with prototypes. If a program would like to make use of objects representing screen coordinates, first construct a prototype:

    Coordinate2D = clone(empty_object)
    Coordinate2D.add_field(x).add_field(y)
Like fields, methods can be added to the prototype:

    Coordinate2D.add_method(clear)
    Coordinate2D.clear = {self.x = 0; self.y = 0}
Next to create an object of type coordinate just clone the prototype:

    location = clone(Coordinate2D)
    location.x = 10
    location.y = 16
Prototype based systems are appealing because of the underlying language semantics and runtime implementation are very simple.

Smalltalk, CLU, Common Lisp's CLOS (The Art of the Meta-Object Protocol), and Self all inspired design decisions that went into the Tivoli Systems distributed programming framework.

Re:Deep JavaScript by MispelledToyota on Thursday June 10, 2021 @03:42PM (#27464757)
I don't think that's how prototypes work in JavaScript though. The newly created objects refer to a chain of prototype references, and changes to the underlying prototypes will affect already existing objects.
Re:Deep JavaScript by todd8 on Thursday June 10, 2021 @10:14PM (#27468598)
My example was a simple one, and you are right, Javascript objects contain a reference to their prototype object from which they are cloned and via which they can inherit behavior. However, this is handled a bit differently in Self and in the original Tivoli Systems actors. The details between these systems are different so my example left out many interesting details.
Re:Deep JavaScript by rauschma on Thursday June 10, 2021 @11:22AM (#27461773)
In JavaScript, classes are mostly just a slightly weird way of setting up prototype chains.

Diagrams help me understand how this works. At the following link, you can see the source code of a simple class and a diagram (section 29.2.2) that shows how all involved objects are connected: https://exploringjs.com/impatient-js/ch_proto-chains-classes...

Re:Deep JavaScript by chriswarbo on Thursday June 10, 2021 @11:55AM (#27462163)
> how does that "map" to "classic" inheritance, from Java or C++

I'd recommend doing it in two steps.

First, you need to get from the Java/C++ perspective of "classes are compile-time templates" to a perspective of "everything is an object". Python is a good example of the latter, as is Smalltalk (the latter is more 'extreme', but also less widely used):

    $ python3
    Python 3.8.9 (default, May 27 2021, 03:09:34) 
    [Clang 7.1.0 (tags/RELEASE_710/final)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> class A:
    ...   pass
    ... 
    >>> myA = A()
    >>> myA
    <__main__.A object at 0x10670c490>
    >>> A
    <class '__main__.A'>
    >>> myA.__class__
    <class '__main__.A'>
    >>> class B(A):
    ...   x = 123
    ... 
    >>> myA.__class__ = B
    >>> myA.x
    123
    >>>
Once you're comfortable with that, you can take the second step: from a Python/Smalltalk perspective of "everything is an object; when a slot isn't found in the instance, we fall back to looking in its class", to reach the Javascript/Self perspective of "everything is an object; when a slot isn't found in an object, it can tell us to look in another object". That 'other object' is the prototype.

All we're doing in the second step is removing a distinction: Python/Smalltalk have a built-in notion of "class", where some objects are classes and others aren't. Javascript/Self just have objects: we can use any object as a prototype for any other.

Re:Deep JavaScript by sesm on Thursday June 10, 2021 @12:23PM (#27462474)
There is a big difference between Java and C++ classes. In C++ classes are not present at runtime, but in Java they are present at runtime, are accessible via reflection API and can be loaded dynamically at runtime.
Re:Deep JavaScript by turndown on Thursday June 10, 2021 @10:57AM (#27461502)
A class is a blueprint you go to for constructing new objects. A prototype is an object you create once that is copied to a variable when the constructor is called. That is how I understand it, but maybe someone else can explain further.
Re:Deep JavaScript by k__ on Thursday June 10, 2021 @11:07AM (#27461593)
You can think of a prototype as a fallback for your object.

If something doesn't exist on your object, JS will check if it has a prototype and look there transparently.

Now, if you got a prototype chain, JS will move through it in the hope to find what you wanted to access on the original object.

try to access obj.a

not there?

try to access obj.prototype.a

not there?

try to access obj.prototype.prototype.a

etc.

The nice thing is "this" will usually (if you call a function as method and not pass a reference of it around for callbacks and such) refer to the object and not the prototype. Also, writes happen on the object.

Re:Deep JavaScript by MispelledToyota on Thursday June 10, 2021 @03:38PM (#27464721)
I think Kyle Simpson's You Don't Know JS does a good job about this. But on the other hand, it seems like it's usually safer to keep it simple, treating it more or less as classical and using classes, to make a codebase that others can relate to well.