Whenever anyone compares JavaScript with Self, I cringe. The name of the seminal Self paper was "SELF: The Power of Simplicity" [1]. JavaScript totally missed the boat on simplicity (the entire POINT of Self), and also totally missed a couple of important features that make Self Self [2]:

1) "prioritized multiple inheritance": Inherit from multiple parent objects: you can inherit through any number of parent slots in a Self object, not just one __proto__ or super or whatever, like JavaScript. There are well defined rules that determine the priority of parents.

2) "dynamic inheritance": Dynamically change which parents you inherit from at runtime. In Self, changing who you inherit from at runtime is a useful programming technique, and the VM implements it efficiently (which is why Self is so interesting and has been so influential). But JavaScript sets the prototype when you "new" an object, and it stays that way.

Self is simple because there's nothing but objects, all the way down. Everything is the same kind of object. Nothing is special.

JavaScript does this weird arbitrary thing by using functions as constructors, and also as prototypes, for no particular reason. Those special constructor functions should never be called normally, they should always be called indirectly with "new". And it means you can only have one constructor. So why the hell are they functions, if you shouldn't ever call them? It's just another way to fuck up, due to pointless and arbitrary complexity.

Being that weird way doesn't make JavaScript any more powerful or expressive or efficient, just more complicated, harder to understand, and easier to make subtle inscrutable mistakes.

JavaScript punted on the important parts of Self at least as much as it punted on the important parts of Scheme (like call/cc).

However at least there's a perfectly reasonable excuse for not supporting call/cc if you have to efficiently interoperate with C code, native libraries and a garbage collector, and the entire system isn't written in pure Scheme.

But there was no legitimate excuse for screwing up the great things about Self that, if done correctly, would have made JavaScript simpler and cleaner and more beautiful.

[1] Self: The Power of Simplicity:
http://www.selflanguage.org/_static/published/self-power.pdf

>Occam’s razor. Throughout the design, we have aimed for conceptual economy:

>• As described above, SELF’s design omits classes and variables. Any object can
perform the role of an instance or serve as a repository for shared information.

>• There is no distinction between accessing a variable and sending a message.

>• As in Smalltalk, the language kernel has no control structures. Instead, closures
and polymorphism support arbitrary control structures within the language.

>• Unlike Smalltalk, SELF objects and procedures are woven from the same yarn
by representing procedures as prototypes of activation records. This technique
allows activation records to be created in the same way as other objects, by
cloning prototypes. In addition to sharing the same model of creation,
procedures also store their variables and maintain their environment
information the same way as ordinary objects, as described in Section 4.

[2] Parents are Shared Parts: Inheritance and Encapsulation in Self:
http://bibliography.selflanguage.org/_static/parents-shared-...

>This paper describes the inheritance and encapsulation mechanisms we designed
and implemented in one prototype-based language, SELF. Our design
is based on the philosophy that an object’s parents should be treated as shared parts
of the object, and that inheritance should be a simple, declarative way to maximize
the possibilities for sharing. This paper describes two heretofore unpublished innovations:
a prioritized multiple inheritance scheme that unifies unordered and
ordered multiple inheritance, and an object encapsulation model that provides
many of the benefits of class-based encapsulation in a language without classes. In
addition, our inheritance system supports directed and undirected resends to
forward messages to an object’s ancestors, a unique sender path tiebreaker rule
that resolves many ambiguities between unrelated unordered parents, and dynamic
inheritance, which allows an object to change its parents at run-time to effect
significant behavioral changes due to changes in its state.