Understanding the difference between classical and prototypal inheritance - javascript

For the past week I've been trying to understand the difference between class based and prototypical inheritance. Having worked with PHP and JavaScript, I expected to grasp this rather quickly, but I just can't wrap my head around this – I always have the feeling that I miss something.
I've learned that a class is like a blueprint defining an object's characteristics. When a class is instantiated, an object is constructed according to the blueprint. When inheritance comes into play, the blueprint can only be adopted completely but methods can be overridden.
But what is a prototype then? Isn't it also like a blueprint, but already implemented (hence the name "prototype")? So with inheritance, you can only point to already existing functions?
The following may seem silly but thats the way I try to understand things.
In more human terms: A class can be regarded as architectural plan, as soon as it get's instantiated small workers start building an object according to that plan. To inherit something, the complete plan is built again, in addition to new details (that may replace existing details).
With prototypes, the workers instead start copying an already existing object and start looking at it's main characteristics (stored on something called the prototype). To inherit from another object, they just put a sign somewhere saying "You are looking for function X? Please this way – mind the gap between objects".
Is this distinction correct?

It seems to me that you actually already got the point.
Class based OO
As you already mentioned, in class-based object oriented languages (like Java) a class is a blueprint for every future object. For the instantiation of an object the blueprint (the class you created) gets copied for this object. This means that in case you change the class after you instantiate your object the previously created object won't have that changes.
When it comes to inheritance: Let's say you have a class Person. You want to create another class Student that inherits from Person. Student is basically a copy of the blueprint Person which can extend the functionality of the blueprint. So your example is very accurate!
This is very useful in complex but rather static OO-structures!
Prototype based
Prototype based languages like JavaScript don't follow this templating kind of approach. Your example hit it pretty good again. You basically just create an object and reference to another object (your prototype). All the functionality you put in your prototype will be shared by all the objects that reference to that prototype object. However, it is important to understand that you don't make copies of blueprints or templates. You are always working with objects.
So you could create a Person Object. That holdsmethods like "sayHello". If you create concrete person e.g. Joe you just create another object and link it to the Person object. So if you try Joe.sayHello() it will look through the Joe object properties and won't find the sayHello method so it will jump over to the concrete Person object. Just like you said with your example.
I don't really like the expression inheritance in prototype based languages because it does not really exist. You don't make a copy of a blueprint and extend its functionality. Inheritance basically works by chaining objects together. For instance the example above. You can have a Person object. Every regular person object (e.g. Joe) has the Person Object as a prototype. Now you create a Student object which has the Person as a prototype. Another object (e.g. StudentJoe) can have Student as a prototype. So it can go through the chain all the way up to person to access its methods.
To keep it short ;): prototype based languages only work with concrete objects which are linked together (prototypes) and not with blue prints and templates.
The advantage of this approach is being dynamic (that's why this approach is commonly used in the web). As you never work with templates but with concrete objects every change in the prototype-chain will always have effect on every object (in terms of accessable functionality) - no matter when it was created.
I hope this helped. There is a good book called You don't know JavaScript - this & object prototype which explains this topic based on JavaScript really well.

Related

Class syntax in javascript and OOP paradigm [duplicate]

One of the major advantages with Javascript is said to be that it is a prototype based language.
But what does it mean that Javascript is prototype based, and why is that an advantage?
Prototypal inheritance is a form of object-oriented code reuse. Javascript is one of the only [mainstream] object-oriented languages to use prototypal inheritance. Almost all other object-oriented languages are classical.
In classical inheritance, the programmer writes a class, which defines an object. Multiple objects can be instantiated from the same class, so you have code in one place which describes several objects in your program. Classes can then be organized into a hierarchy, furthering code reuse. More general code is stored in a higher-level class, from which lower level classes inherit. This means that an object is sharing code with other objects of the same class, as well as with its parent classes.
In the prototypal inheritance form, objects inherit directly from other objects. All of the business about classes goes away. If you want an object, you just write an object. But code reuse is still a valuable thing, so objects are allowed to be linked together in a hierarchy. In javascript, every object has a secret link to the object which created it, forming a chain. When an object is asked for a property that it does not have, its parent object will be asked... continually up the chain until the property is found or until the root object is reached.
Each function in JavaScript (which are objects themselves) actually has a member called "prototype", which is responsible for providing values when an object is asked for them. Having this member allows the constructor mechanism (by which objects are constructed from functions) to work. Adding a property to the prototype of a function object will make it available to the constructed object, as well as to all of the objects which inherit from it.
Advantages
There may not be a hard and fast rule as to why prototypal inheritance is an advantageous form of code-reuse. Code reuse itself is advantageous, and prototypal inheritance is a sensible way of going about it. You might argue that prototypal inheritance is a fairly simple model of code reuse, and that code can be heavily reused in direct ways. But classical languages are certainly able to accomplish this as well.
Sidenote: #Andrew Hedges makes a good point, that there are actually many prototypal languages. It's worth noting that these others exist, but also worth noting that none of them are anything close to mainstream. NewtonScript seemed to have some traction for a while, but died with its platform. It's also possible to extend some modern languages in ways which add prototypal capabilities.
A prototype-based language, does not make the distinction of classes vs objects: it simply has objects. A prototype-based language has the notion of a prototypical object, an object used as a template from which to get the initial properties for a new object. Any object can specify its own properties, either when you create it or at run time. In addition, any object can be associated as the prototype for another object, allowing the second object to share the first object's properties.
Prototype-based programming is a style of object-oriented programming where classes are not present, and behavior reuse (or inheritance in class-based languages) is performed by cloning existing objects that serve as prototypes.
The advantage/disadvantage is that, we can create new kinds of objects at run time without need for defining classes (static code). Like most features it is upto the developer to turn it to a advantage/disadvantage.
Above is possible because objects are essentially functions in java script (closures too).
Instead of declaring a class structure, you can create objects of the same type, and add to their definition any time you like using the object's prototype.
It's more flexible than the normal way of doing things.
After reading all the answers this is the conclusion
1) Inheritance in which objects are inherited directly from other objects
2) That does not use classes
3) Also called instance based programming or classless prototype oriented programming
4) Behaviour reuse is performed by cloning existing objects that serve as prototypes
5) Object used as template from the new object get initial properties
If you just use objects at runtime instead of a class at compile to build new objects, this opens up the possibility of extending an object without knowing any details about it. Of course, it may become a disadvantage pretty quickly depending on usage. I make no assumptions about the language here, so it is applicable to languages other than javascript which are not as dynamic.
myobject.prototype=unkownobject;
myobject.newproperty=1;
You may get the object from just about anywhere; your own code, from the network, from the database, from external linkage and so on.
Note that, a language don't have to implement prototype inheritance like javascript. In javascript, a prototype object is merely shared, so is its properties, among the inheritors. The alternative is copying over all the properties of the prototype to the new object. Each approach has its strengths in different situations. I like the second more but it isn't what javascript does.
Memory conservation is one of the benefits of prototypal inheritance in JS. In a language like Java, objects generate their own copies of the superclass' instance variables and methods, while in JS, the "super"-object offers get-access to its variables and methods to each "sub"-object that inherits from it without the need to recreate them.

JavaScript: Constructors With Arguments And Inheritance Therefrom

I've signed up in the hope that someone can finally provide an exposition of Javascript's prototype inheritance that actually works. The specific code I'm interested in, centres upon a library I wrote myself to handle such tasks as the generation of linked lists, binary trees, etc., and for which I defined the following constructor:
function ListLinks(objLink)
{
this.prev = null;
this.next = null;
this.content = objLink;
}
The idea is that the 'prev' and 'next' properties are links to other ListLinks objects, and the 'content' property is a link to the object containing the data being inserted into the list or tree.
Now, using references to the prototype object associated with the above ListLinks object, I successfully added some class methods, to perform tasks such as entry insertion, entry removal, list traversal, and tree traversal. These all work nicely.
Now, because I want to take advantage of this functionality in a new object type, I thought that the intelligent approach would be to inherit that functionality, including all the properties and methods, from the ListLinks object in the new object. The new object I called a RenderTree object, because I'm interested in generating a binary tree of graphical rendering data. The idea being that I can sort my rendering data on input into the tree by distance from the viewing camera, and use an in-order traversal of the tree to implement the Painter Algorithm. But that isn't my problem.
My problem is persuading the JavaScript prototype inheritance mechanism to allow my RenderTree object to inherit the ListLinks object's properties and methods, without throwing all sorts of annoying bugs at me.
The trouble is, because the ListLinks constructor takes arguments, I can't create an instance of the ListLinks object and use that as my prototype in code such as:
RenderTree.prototype = new ListLinks(object);
because doing so forces ALL instances of RenderTree objects to have the 'content' property set to the same value, and even attempting explicitly to modify that value in created instances fails. Yet, without doing something of the above sort, I can't change the identity of the instantiated objects - they retain the identity of a ListLinks object (the parent), instead of acquiring the identity of the child (the RenderTree object), which was the whole point of using the above, and the subsequent:
RenderTree.prototype.constructor = RenderTree;
This was done so that the RenderTree object could inherit ALL of the ListLinks objects' properties and methods, yet have additional functionality added to facilitate the generation of the rendering data I intend to be inserted into a binary tree of RenderTree objects, said objects having their own distinctive identity.
Now, one of the weird aspects of this, from my standpoint, is that whilst the 'content' property of the RenderTree object becomes, in effect, immutable when doing this, the same isn't true of the 'next' and 'prev' properties. Which suggests to me that there's some horrible inconsistency lurking at the heart of the inheritance mechanism that will simply make me want to go back to class based languages, that don't exhibit this annoying behaviour. Performing the above task in a language such as C++, defining a ListLinks Class and then defining a RenderTree Class as an extension thereof, doesn't drop this unwanted hassle in my lap.
Now, to compound the issue, I've seen no less than four different expositions on the subject (two of them from here, as it happens), including using Object.create(), using super constructor invocation (this was covered in more detail on the page of one Ben Nadel), and using fake constructors. None of them I've tried has worked. All that happens is that previous methods that mostly worked in the old code end up being broken spectacularly when I try one of the new methods. Indeed, I initially learned about the whole business from the web page of someone called Toby Ho (I would have posted a link, but I've just been told I can't have two webpage links in my post, all helping to add to the frustration of trying to solve this problem, thank you), but that page was of no help with my particular problem either, other than solving the matter of allowing me to have class method functionality in my code.
Now, given the huge amount of frustration I've had over this, is it too much to ask, to see someone provide me with an explanation of this inheritance mechanism that [1] is in accord with the observations I've made above, [2] produces something that works, and [3] demonstrates that someone out there does actually understand what it's doing? Only I'm increasingly coming to the conclusion that whoever designed the latest incarnation of JavaScript just made up whatever looked good at the time, then threw it into the interpreter without giving a hoot about whether or not programmers trying to use it could make any sense of it.
If I can't alight upon some means of achieving what should be something trivial, and has been trivial in class based languages I'm familiar with, then I think I'll relegate JavaScript to the bin as far as serious work is concerned.

Do all object-oriented languages create a lot of duplicate information in memory?

I am reading a book about JS and other web stuff now and that's what I encountered about the prototype keyword:
The prototype keyword can save you a lot of memory. In the User class, every instance will contain the three properties and the method. Therefore, if you have 1,000 of these objects in memory, the method showUser will also be replicated 1,000 times. However, because the method is identical in every case, you can specify that new objects should refer to a single instance of the method instead of creating a copy of it.
Don't any object-oriented language behaves just like this? I have read some books about C++, C# and never been told about that. I think it follows to create static methods in class and call them from not static methods, or it is not a problem in other languages and I should not even remember about that?
In C# and other statically typed langauges, the methods each class users are defined once and then each instantiation of that object refers only to the single definition. As such, there is no need for the same construct as the prototype in JS.
Prototypes is a very different way of doing OOP.
With this paradigm, objects contain both code and data. That's why if you duplicate your objects thousands of times, there will be thousands of copies of the methods. In the more common inheritance paradigm, classes only have a reference to their methods, the method is outside the objects.
Very few languages follow this paradigm, but Javascript is one of them. Most OOP languages, like C# or C++, don't have the kind of prototypes you're talking about, so they don't have this particular problem.

Use closure to make methods private in prototype

I am using prototype 1.4 in our project,I used to create Class in this manner:
1) Manner1
var Person=Class.create();
Person.prototype={
initialize:function(name,age){
this._check(name,age);
this.name=name;
this.age=age;
},
say:function(){
console.log(this.name+','+this.age);
}
_check:function(name,age){
if(typeof(name)!='string' || typeof(age)!='number')
throw new Error("Bad format...");
}
}
However,in the above code,the method of Person "_check" can be called outside which is not my expected.
And in my former post ,thanks for 'T.J. Crowder',he told me one solution to make the method totally private:
2) Manner2
var Person=(function(){
var person_real=Class.create();
person_real.prototype={
initialize:function(name,age){
_check(name,age);
this.name=name;
this.age=age;
},
say:function(){
console.log(this.name+','+this.age);
}
}
//some private method
function _check(name,age){
//....the check code here
}
return person_real;
})();
Now,the "_check" can not be exposed outside.
But what I am now confusing is that does this manner will cause performance problem or is it the best pratice?
Since one of the reasons we create class(the blueprint) is to reducing the repeat codes which can be reused many times anywhere.
Now look at the "Manner1":
We create a Class "Person",then we puts all the instance methods to the prototype object of class Person.
Then each time we call the
var obj=new Person('xx',21);
the object "obj" will own the methods from the Person.prototype. "obj" itself does not hold any codes here.
However in "Manner2":
Each time we call:
var obj=new Person('xx',21);
A new blueprint will be created,the private methods such as "_check" will be created each time also.
Is it a waste of memory?
Note: maybe I am wrong. But I am really confused. Any one can give me an explaination?
You're getting caught with a couple common problems that people have with Javascript.
Second question first, as its easier to answer. With prototypical inheritance you're only describing the differences between two related objects. If you create a function on the prototype of an object and then make 10000 clones of it, there's still only one function. Each individual object will call that method, and due to how "this" works in Javascript, the "this" in those function calls will point to the individual objects despite the function living in the singular prototype.
Of course when you have unique per-item properties, the unique values for each object, then yes you can can performance issues (I hesitate to use the term "instance" because it doesn't mean the same thing in prototypical inheritance compared to class based inheritance). Since you're no longer benefiting from one single shared function/dataset you lose that benefit. Knowing how to minimize these inefficiencies is one key part of smart, efficient programming in Javascript (and any prototypal inheritance based language). There's a lot of non-obvious tricks to get functionality and data shared with minimal duplication.
The first question is a common class of confusion in Javascript due to the near omnipotence of Function in Javascript. Functions in Javascript single handedly do the jobs of many different constructs in other languages. Similarly, Objects in Javascript fill the role of a lot of data constructs on other languages. This concentrated responsibility brings a lot of powerful options to the table, but makes Javascript a kind of boogieman: it looks like really simple, and is really simple. But it's really simple kind of how like poker is really simple. The's a small set of moving pieces, but the way they interact begets a much deeper metagame that rapidly becomes bewildering.
It's better to understand objects/functions/data in a Javascript application/script/whatever as a constantly evolving system, as this better helps capture prototypal inheritance. Perhaps like a football (american) game where the current state of the game can't really be captured without knowing how many downs there is, how many timeouts remain, what quarter you're in, etc. You have to move with the code instead of looking at it like most languages, even dynamic ones like php.
In your first example all you're doing essentially is using Class.create to get the initialize() function automatically called and to handle grandparent constructor stuff automatically so otherwise similar to just doing:
var Person = function(){ this.initialize.call(this, arguments) };
Person.prototype = { ... }
Without the grandparent stuff. Any properties set directly on an object are going to be public (unless you're using ES5 defineProperty stuff to specifically control it) so adding _ to the beginning of the name won't do anything outside of conventions. There is no such thing as a private or protected member in javascript. There is ONLY public so if you define a property on an object it is public. (again discounting ES5 which does add some control to this, but it's not really designed to fill the same as private variables in other languages and it shouldn't be used or relied on in the same way).
Instead of private members we have to use scope to create privacy. It's important to remember that Javascript only has function scoping. If you want to have private members in an Object then you need to wrap the whole object in a bigger scope (function) and selectively make public what you want. That's an important basic rule that for some reason I rarely see succincly explained. (other schemes exist like providing a public interface to register/add functions into a private context, but they all end with everything that's sharing having access to a private context build by a function, and usually are way more complicated than needed).
Think of it this way. You want to share these members inside the object, so all the object members need to be within the same scope. But you don't want it shared on the outside so they must be defined in their own scope. You can't put them as members ON the public object since Javascript has no concept of anything besides public variables (ES5 aside, which can still be screwed with) you're left with function scope as the only way to implement privacy.
Fortunately this isn't painful because you have a number of effective, even smooth ways to do this. Here comes in Javascript's power as a functional language. By returning a function from a function (or an object containing functions/data/references) you can easily control what gets let back out into the world. And since Javascript has lexical scoping, those newly unleashed public interfaces still have a pipe back into the private scope they were originally created in, where their hidden brethren still live.
The immediately executed function function serves the role of gatekeeper here. The objects and scope aren't created until the function is run, and often the only purpose for the container function is to provide scope, so an anonymous immediately executing function fits the bill (neither anonymous or immediately executing are required though). It's important to recognize the flexibility in Javascript in terms of construction an "Object" or whatever. In most languages you carefully construct your class structure and what members each thing has and on and on and on. In Javascript, "if you dream it you can make it" is essentially the name of the game. Specifically, I can create an anonymous function with 20 different Objects/Classes/whatever built inside of it and then ad-hoc cherry pick a method or two from each and return those as a single public Object, and then that IS the object/interface even though it wasn't until two seconds before I did return { ...20 functions from 20 different objects... }.
So in your second example you're seeing this tactic being used. In this case a prototype is create and then a separate function is created in the same scope. As usual, only one copy of the prototype will exist no matter how many children come from it. And only one copy of that function exists because that containing function (the scope) is only called once. The children created from the prototype will not have access to call the function, but it will seem like they do because they're getting backdoor access through functions that live on the prototype. If a child goes and implements its own initialize in that example it will no longer be able to make use of _check because it never had direct access in the first place.
Instead of looking at it as the child doing stuff, look at it as the parent/prototype tending to the set of functions that live on it like a central phone operator that everything routes through, with children as thin clients. The children don't run the functions, the children ping the prototype to run them with this pointing at the caller child.
This is why stuff like Prototype's Class becomes useful. If you're implementing multilevel inheritance you start running into holes where prototypes up the chain miss out on some functionality. This is because while properties/functions in the prototype chain automagically show up on children, the constructor functions do not similarly cascade; the constructor property inherits same as anything else, but they're all named constructor so you only get the direct prototype's constructor for free. Also constructors need to be executed to get their special sauce whereas a prototype is simply a property. Constructors usually hold that key bit of functionality that sets up an objects own private data which is often required for the rest of the functionality to work. Inheriting a buttload of functions from a prototype chain doesn't do any good if you don't manually run through the constructor chain as well (or use something like Class) to get set up.
This is also part of why you don't usually see deep inheritance trees in Javascript and is usually peoples' complaints about stuff like GWT with those deep Java-like inheritance patterns. It's not really good for Javascript and prototypical inheritance. You want shallow and wide, a few layers deep or less. And it's important to get a good grasp on where in the flow an object is living and what properties are where. Javascript does a good job of creating a facade that makes it look like X and Y functionality is implemented on an object, but when you peer behind you realize that (ideally) most objects are mostly empty shells that a.) hold a few bits of unique data and b.) are packaged with pointers to the appropriate prototype objects and their functionality to make use of that data. If you're doing a lot of copying of functions and redundant data then you're doing it wrong (though don't feel bad because it's more common than not).
Herein lies the difference between Shallow Copy and Deep Copy. jQuery's $.extend defaults to shallow (I would assume most/all do). A shallow copy is basically just passing around references without duplicating functions. This allows you to build objects like legos and get a bit more direct control to allow merging parts of multiple objects. A shallow copy should, similar to using 10000 objects built from a prototype, not hurt you on performance or memory. This is also a good reason to be very careful about haphazardly doing a deep copy, and to appreciate that there is a big difference between shallow and deep (especially when it comes to the DOM). This is also one of those place Javascript libraries care some heavy lifting. When there's browser bugs that cause browsers to fail at handling the situations where it should be cheap to do something because it should be using references and efficiently garbage collecting. When that happens it tends to require creative or annoying workarounds to ensure you're not leaking copies.
A new blueprint will be created,the private methods such as "_check" will be created each time also. Is it a waste of memory?
You are wrong. In the second way, you execute the surrounding function only one time and then assign person_real to Person. The code is exactly the same as in the first way (apart form _check of course). Consider this variation of the first way:
var Person=Class.create();
Person.prototype={
initialize:function(name,age){
_check(name,age);
this.name=name;
this.age=age;
},
say:function(){
console.log(this.name+','+this.age);
}
}
function _check(name,age){
//....the check code here
}
Would you still say that _check is created every time you call new Person? Probably not. The difference here is that _check is global and can be accessed form any other code. By putting this piece in a function and call the function immediately, we make _check local to that function.
The methods initialize and say have access to _check, because they are closures.
Maybe it makes more sense to you when we replace the immediate function with a normal function call:
function getPersonClass(){
var person_real=Class.create();
person_real.prototype={
initialize:function(name,age){
_check(name,age);
this.name=name;
this.age=age;
},
say:function(){
console.log(this.name+','+this.age);
}
}
//some private method
function _check(name,age){
//....the check code here
}
return person_real;
}
var Person = getPersonClass();
getPersonClass is only called once. As _check is created inside this function, it means that it is also only created once.

prototype based vs. class based inheritance

In JavaScript, every object is at the same time an instance and a class. To do inheritance, you can use any object instance as a prototype.
In Python, C++, etc.. there are classes, and instances, as separate concepts. In order to do inheritance, you have to use the base class to create a new class, which can then be used to produce derived instances.
Why did JavaScript go in this direction (prototype-based object orientation)? what are the advantages (and disadvantages) of prototype-based OO with respect to traditional, class-based OO?
There are about a hundred terminology issues here, mostly built around someone (not you) trying to make their idea sound like The Best.
All object oriented languages need to be able to deal with several concepts:
encapsulation of data along with associated operations on the data, variously known as data members and member functions, or as data and methods, among other things.
inheritance, the ability to say that these objects are just like that other set of objects EXCEPT for these changes
polymorphism ("many shapes") in which an object decides for itself what methods are to be run, so that you can depend on the language to route your requests correctly.
Now, as far as comparison:
First thing is the whole "class" vs "prototype" question. The idea originally began in Simula, where with a class-based method each class represented a set of objects that shared the same state space (read "possible values") and the same operations, thereby forming an equivalence class. If you look back at Smalltalk, since you can open a class and add methods, this is effectively the same as what you can do in Javascript.
Later OO languages wanted to be able to use static type checking, so we got the notion of a fixed class set at compile time. In the open-class version, you had more flexibility; in the newer version, you had the ability to check some kinds of correctness at the compiler that would otherwise have required testing.
In a "class-based" language, that copying happens at compile time. In a prototype language, the operations are stored in the prototype data structure, which is copied and modified at run time. Abstractly, though, a class is still the equivalence class of all objects that share the same state space and methods. When you add a method to the prototype, you're effectively making an element of a new equivalence class.
Now, why do that? primarily because it makes for a simple, logical, elegant mechanism at run time. now, to create a new object, or to create a new class, you simply have to perform a deep copy, copying all the data and the prototype data structure. You get inheritance and polymorphism more or less for free then: method lookup always consists of asking a dictionary for a method implementation by name.
The reason that ended up in Javascript/ECMA script is basically that when we were getting started with this 10 years ago, we were dealing with much less powerful computers and much less sophisticated browsers. Choosing the prototype-based method meant the interpreter could be very simple while preserving the desirable properties of object orientation.
A comparison, which is slightly biased towards the prototypes based approach, can be found in the paper Self: The Power of Simplicity. The paper makes the following arguments in favor of prototypes:
Creation by copying. Creating new objects from prototypes is accomplished by a simple operation, copying, with a simple biological
metaphor, cloning. Creating new objects from classes is accomplished
by instantiation, which includes the interpretation of format
information in a class. Instantiation is similar to building a house
from a plan. Copying appeals to us as a simpler metaphor than
instantiation.
Examples of preexisting modules. Prototypes are more concrete than classes because they are examples of objects rather than descriptions
of format and initialization. These examples may help users to reuse
modules by making them easier to understand. A prototype-based system
allows the user to examine a typical representative rather than
requiring him to make sense out of its description.
Support for one-of-a-kind objects. Self provides a framework that can easily include one-of-a-kind objects with their own behavior.
Since each object has named slots, and slots can hold state or
behavior, any object can have unique slots or behavior. Class-based
systems are designed for situations where there are many objects with
the same behavior. There is no linguistic support for an object to
possess its own unique behavior, and it is awkward to create a class that is guaranteed to have only one
instance [think singleton
pattern]. Self suffers from neither of these disadvantages. Any object
can be customized with its own behavior. A unique object can hold the
unique behavior, and a separate "instance" is not needed.
Elimination of meta-regress. No object in a class-based system can be self-sufficient; another object (its class) is needed to express
its structure and behavior. This leads to a conceptually infinite
meta-regress: a point is an instance of class Point, which is an
instance of metaclass Point, which is an instance of metametaclass
Point, ad infinitum. On the other hand, in prototype-based systems
an object can include its own behavior; no other object is needed to
breathe life into it. Prototypes eliminate meta-regress.
Self is probably the first language to implement prototypes (it also pioneered other interesting technologies like JIT, which later made its way into the JVM), so reading the other Self papers should also be instructive.
You should check out a great book on JavaScript by Douglas Crockford. It provides a very good explanation of some of the design decisions taken by JavaScript creators.
One of the important design aspects of JavaScript is its prototypal inheritance system. Objects are first class citizens in JavaScript, so much that regular functions are also implemented as objects ('Function' object to be precise). In my opinion, when it was originally designed to run inside a browser, it was meant to be used to create lots of singleton objects. In browser DOM, you find that window, document etc all singleton objects. Also, JavaScript is loosely typed dynamic language (as opposed to say Python which is strongly typed, dynamic language), as a result, a concept of object extension was implemented through the use of 'prototype' property.
So I think there are some pros for prototype-based OO as implemented in JavaScript:
Suitable in loosely typed environments, no need to define explicit types.
Makes it incredibly easy to implement singleton pattern (compare JavaScript and Java in this regard, and you'll know what I am talking about).
Provides ways of applying a method of an object in the context of a different object, adding and replacing methods dynamically from an object etc. (things which are not possible in a strongly typed languages).
Here are some of the cons of prototypal OO:
No easy way of implementing private variables. Its possible to implement private vars using Crockford's wizardry using closures, but its definitely not as trivial as using private variables in say Java or C#.
I don't know how to implement multiple inheritances (for what its worth) in JavaScript yet.
The difference between mainstream OOP class-based languages such as c# or java and prototype bases languages such as javascript is the ability to modify object types at runtime whilst in c# or java they gave up this ability in favor of static type checking by making classes fixed at compile time. JS has always been closer to the first original design of OOP of alan Kay and languages such as Smalltalk or simula.
this is achieved by making the blueprint itself an instance, types in prototype-based are actual instances that can be accessed and modified at runtime, in Javascript this is really easy using the prototype object, since every object type has this object.
example: type funcName.prototype.myNewMethod= function{ console.log("hello world")}

Categories

Resources