Beyond Classes
Smalltalk introduced a simple method of creating objects via factories known as classes. Self, first introduced in 1986, went in a slightly different direction by using prototypes.
In Self, instead off defining the object and then instantiating it, you would clone and object and then add methods and instance variables to it. This is also possible in Smalltalk, but the language isn’t really designed for it.
This style, known as prototype-based, object-oriented programming is now one of the most widespread programming paradigms due to the fact that it was chosen by Netscape in the mid-1990s as the model for its JavaScript scripting language.
Since then, the use of JavaScript, later standardized as ECMAScript, has found its way into a huge number of web pages and web applications.
Prototype-based programming is generally considered more flexible than class-based programming, and is often more understandable. When a specific behavior is needed in only a small number of instances of an object, it is much easier to only add it to this small number in prototype-based languages.
Class-based languages typically require more code to be written to create a specialized version of a class, which encourages bloat in a smaller number or a large spread of classes that are hard to read.
The focus on inheritance in class-based languages makes it much harder to add different, orthogonal, sets of behavior to a group of objects (multiple inheritance helps here, but comes with its own problems).
Prototype-based languages, with their dynamically changing types, are much harder to compile to heavily optimized code. This is becoming less important, as the wide use of JavaScript has shown, but is still a concern in some areas.
The developers of the Lisaac language attempted to address this by introducing static typing to a prototyped language, which allows a huge body of research into optimizing languages like C to be applied.