Easy JavaScript Prototype Inheritance |
Written by Ian Elliot | |||
Friday, 18 May 2012 | |||
Page 1 of 2 Still confused about prototype-based inheritance? Still think that JavaScript needs classes and full inheritance? It all looks a lot simpler if you try to forget the classical way of doing things and concentrate on how JavaScript handles objects. I've written about the way people try to turn JavaScript into other languages that they feel more comfortable with. In particular, the way that Java and C# programmers try to reinvent typed, class-based, object-oriented programming. This is simply the wrong paradigm for JavaScript which is weakly typed and instance-based. When you add in the fact that many programmers now think that inheritance is the wrong way to organize a program, then you can see that all of the efforts to make JavaScript into a classical object-oriented language are not only a misunderstanding, but a potentially damaging effort. First, let's get the classical paradigm clearly stated. Languages such as Java and C# make use of a type system to build a hierarchy of types. Classes are used to extend the type system using inheritance. The entire type system starts from a base type - usually object and everything derives from object. This produces a strict tree structure of classes, objects and types. It also introduces additional ideas, such as static or class methods and properties, the need to to cast from one type to another and polymorphism. And just when you thought it was all working well, someone introduces the idea of generics and slowly starts to release the iron grip of strict typing. JavaScript, on the other hand, is a language that really regrets that there is any need to distinguish between data types. As a result it is weakly typed and there is no type hierarchy, except in the very limited sense that there are objects, and there is a simplest object {} which has no properties or methods. After this you simply create objects by adding properties and methods as you like and at any time that you like. Surely this is chaos? Well yes and no, it all depends on how you look at it. The Constructor ObjectIf you regard all objects as just things with properties and methods and no relationships to other objects, then the situation has no structure at all and this makes it more difficult to control the complexity of an application. However there is an organizing principle at work and it is all based on the relationship between an object and its constructor object. Notice that in most languages an object has a constructor function, but in JavaScript the constructor is an object in its own right. All this works because in JavaScript a function is also an object - every function, even if it isn't a constructor, is an object. A constructor is simply a function object that is used with the new keyword and which returns the object it creates. For example:
Once you have the constructor you can create as many identical objects as you require. For example:
Every object created by a constructor keeps a record of the constructor object that created it in a special constructor property. This is a one-to-many relationship - one constructor object creates many objects each of which keeps a reference to its constructor. It is important to realize that the constructor really does build a brand new object every time it is used. There is no reuse of methods or properties and this can be a waste of resources. Why does every point object you create need its own completely independent copy of a move method? Prototype ObjectsTo avoid this inefficiency JavaScript uses the idea of a prototype object. A single constructor object is shared by all of the objects it creates and therefore makes an obvious place to store any methods that are to be shared. The constructor has a prototype property and this references an object that can be used to provide methods to any object the constructor creates. If you try to use a method or a property that isn't defined for a particular object then the reference is passed back to its constructor's prototype object. You can see that this, once again, is many-to-one. A single prototype object is stored as part of the constructor object ant this provides "default" methods and properties for all the objects the constructor creates. Notice that the prototype object is associated with the constructor and not with the any instances of the object. The constructor not only creates the object it also keeps track of its prototype and hence the relationship between the constructor an an object it creates doesn't go away as soon as the construction is over. The prototype mechanism is often described as JavaScript's form of inheritance, but this really isn't what it is all about. It is simply a way of reducing the overhead of having to have copies of the code for a method in each object created. For example, if you use the constructor given earlier then every object created has its own copy of myMethod. If you create a thousand copies of myObject then the code in myMethod will be reproduced a thousand times and take up a thousand times the space. However, if you define it as a method of the constructor's prototype property then there is just one copy of the code, no matter how many copies of myObject you care to create.
Notice that defining properties within a prototype object only provides initial values because as soon as you assign to a prototype-provided property a local copy is created. This is also true of methods in that if you redefine a method then it is stored in the object and replaces the prototype's method of the same name. There are some tricky things you can get up to with the prototype mechanism. For example you can redefine a method in the prototype object at runtime and this changes all of the methods used by the objects that have been created. You can also add methods and properties to the built-in objects such as String, but none of these techniques are good ideas. <ASIN:0470344725> <ASIN:0596806752> <ASIN:0470525932> <ASIN:059680279X> |
|||
Last Updated ( Saturday, 19 May 2012 ) |