Prototypal Inheritance in Javascript

ref – http://aaditmshah.github.io/why-prototypal-inheritance-matters

execute as constructor function vs standard function

In javascript, we have the “new” keyword, which is used with functions in order to use it as a constructor function.
If you use it without the “new” keyword, you are simply calling it as a standard function.

Problem with using “new”

We create a function Person. Then use new to call it as a “constructor” function.

But there’s a problem. We can’t use any of Function’s prototype functions such as “apply”, “call”, etc.

If we do make “new” into a function, then we can use “apply”, “call”…etc:

JS has prototypal inheritance, so its possible to implement “new” as a function:

“new” cannot be used in conjunction with functional feature.
“new” masks true prototypal inheritance in JS.

JS is a prototypal language, try not to use “new”

Create objects “out of nothing”

Cloning Existing Object

a)

There is an existing object.

We create an empty object where its prototype is that of the existing object.

b)

We create an empty object that has __proto__ pointing to Object’s prototype.
Then we attach a property called “area” as a function.

Extending a Newly Created Object

In the above example, we cloned the rectangle object and called it rect, but before we may use the area function of rect we need to extend it with width and height.

We add properties width and height and initialize numbers to the properties.
Then, we are able to call the “area” function.

However, this way is not good because we need to manually define width and height on every clone of rectangle

It would be nice to have a function create a clone of rectangle and extend it with width and height properties for us.

Prototypal Pattern

Notice the create function. It uses Object.create(this). This allocates a new empty object, that has __proto__ pointing to rectangle.
This newly created object is referenced by self.
Then, self attaches properties height and width to it, and initialize them to the parameters width/height.

It returns the newly allocated object. Thus, when you use the create function, you literally create a new object with its __proto__ pointing to rectangle. That way, your allocated object can call function area via prototype.

Then can call prototype functions.

Prototypal Pattern vs Constructor Pattern

What we had previous is a Prototypal pattern.

We we have here, is a constructor pattern:

In order to make JavaScript look more like Java, the prototypal pattern was inverted to yield the constructor pattern.

Hence every function in JavaScript has a prototype object and can be used as a constructor.

In addition, it clones the prototype of the constructor and binds it to the “this” pointer of the constructor, returning this if no other object is returned.

Both the prototypal pattern and the constructor pattern are equivalent

Hence you may wonder why anybody would bother using the prototypal pattern over the constructor pattern. After all the constructor pattern is more succinct than the prototypal pattern. Nevertheless the prototypal pattern has many advantages over the constructor pattern, enlisted in the following table:

Constructor Pattern

  • Functional features (call, apply…etc) can’t be used in conjunction with the new keyword
  • Forgetting to use new leads to unexpected bugs and global variables
  • Prototypal inheritance is unnecessarily complicated and confusing. (http://chineseruleof8.com/code/index.php/2018/02/06/prototype-and-inheritance-in-js-non-class/)
  • Prototypal Pattern

  • Functional features (call, apply…etc) can be used in conjunction with create
  • Since create is a function the program will always work as expected
  • Prototypal inheritance is simple and easy to understand
  • The last point may need some explanation.

    The underlying idea is that prototypal inheritance using constructors is more complicated than prototypal inheritance using prototypes.

    prototypal inheritance using prototypes

    First we create a clone of rectangle and call it square.

    Next we override the create function of square with a new create function.

    Finally we call the create function of rectangle from the new create function and return the object is returns.

    prototypal inheritance using constructors

    Using Square as a constructor function, we must call Rectangle.call in order to initialize “this” like a super object.
    That way, when we use new to create it, we’ll work off of a Rectangle object as a super object. Then we can implement whatever we want
    additionally at Square as the child object.

    You can read in detail at http://chineseruleof8.com/code/index.php/2018/02/06/prototype-and-inheritance-in-js-non-class/ (scroll to the very bottom and see “custom example”)

    Sure, the constructor function becomes simpler. However it becomes very difficult to explain prototypal inheritance to a person who knows nothing about it.
    It becomes even more difficult to explain it to a person who knows classical inheritance.

    When using the prototypal pattern it becomes obvious that one object inherits from another object. When using the constructor pattern this is not so obvious because you tend to think in terms of constructors inheriting from other constructors.

    Combining Object Creation and Extension

    First, we want something like this:

    We want to create a new object (with its default functionalities as “this”), but extend it with the properties as mentioned.

    so we pass the extension like so:

    into the extend function. Notice extend function is attached to Object.prototype.
    This is because we want all objects to have this functionality.

    We then log to look at the extension. It is as expected. We see that the extension we passed in has the properties height and width, and initiated to 10, and 5.
    The default functionalities are all in “this”, aka, rectangle.

    We then use default Object’s hasOwnProperty, which says:

    The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).

    Hence, we just have a reference to it to transfer properties from the extension over. And not touch any inherited ones.

    Then, we create a new empty object, with its __proto__ pointing to “this”. Which is rectangle.
    As you can see, the object created is empty, with its proto pointing to the Rectangle “this”.


    output:

    —- allocated object —-
    object:
    {}
    object.__proto__:
    { create: [Function: create], area: [Function: area] }

    In the next step, we’re gunna assign all the properties from the extension object over to our allocated object.

    1) We loop over all the properties in the extension. We’ll get height, width, extend. height and width were the original properties owned by the “extension” object we passed into the extend function. We’ll also get extend, which is the function we attached to Object.prototype

    We call the hasOwnProperty, which decides whether the property is owned the extension object. Properties width and height are. However, extend is not owned. It it extend via Object.prototype.


    output:
    –|height|–
    true
    –|width|–
    true
    –|extend|–
    false

    2) Hence, if the property is owned by the extension object, and it does not exist in the allocated object, then we simply attach it.

    Here, we have the full code. What is returned is a newly allocated object that has the extension properties transferred over. With its __proto__ pointing to “this”, which is rectangle.

    Hence in order to use it, we’ll have rectangle’s create function implement it like so:

    Then use it like so:

    Hence, as you can see, the properties from the extension object is copied over to the allocated object. The allocated object’s __proto__ points to rectangle.


    output:

    { height: 10, width: 5 }
    { create: [Function: create], area: [Function: area] }
    50

    Some of you may have noticed that the object returned by the extend function actually inherits properties from two objects, and not one – the object being extended and the object extending it. In addition the way in which properties are inherited from these two objects is also different.

    In one part, case we inherit properties via delegation. In another, we case we inherit properties via concatenation.

    Differential Inhereitance

    It operates on the principle that most objects are derived from other, more general objects, and only differ in a few small aspects; while usually maintaining a list of pointers internally to other objects which the object differs from.

    Prototypal inheritance in JavaScript is based on differential inheritance. Every object in JavaScript has an internal pointer, called [[proto]], which points to the prototype of that object. The [[proto]] property of objects created “out of nothing” point to null. This forms a chain of objects linked via the internal [[proto]] property (hence called a prototype chain), which ends in null.

    When you try to access a property of an object the JavaScript engine first searches for that property on the object itself. If it cannot find the property on the object then it delegates the property access to the prototype of the object. In this way the property access traverses up the prototype chain until the property is found (in which case it’s returned) or the chain ends in null (in which case undefined is returned).

    TODO – put diagram of hero hierarchy here. put reference here

    Cloning or Concatenate Inheritance

    Most JavaScript programmers would argue that copying the properties of one object to another is not truly a form of inheritance because any modifications to the original object are not reflected on the clone.

    However, modifications to the original object can be propagated to its copies to achieve true prototypal inheritance.

    Concatenation and delegation both have their advantages and disadvantages. They are listed in the following table:

    Delegation

    In JavaScript, an object may have a link to a prototype for delegation. If a property is not found on the object, the lookup is delegated to the delegate prototype, which may have a link to its own delegate prototype, and so on up the chain until you arrive atObject.prototype, which is the root delegate. This is the prototype that gets hooked up when you attach to a Constructor.prototype and instantiate withnew. You can also use Object.create() for this purpose, and even mix this technique with concatenation in order to flatten multiple prototypes to a single delegate, or extend the object instance after creation.

    Any changes to the prototype are automatically reflected on all its clones.
    TODO – use picture

    Property access is slower because it may need to traverse up the prototype chain.
    TODO – use picture

    Objects may only delegate to a single prototype in JavaScript.
    TODO – use picture

    Concatenative Inheritance

    Concatenative inheritance is the process of combining the properties of one or more source objects into a new destination object. Believe it or not, it is the most commonly used form of inheritance in JavaScript.

    Any changes to the prototype need to be propagated to all its clones.
    Property access is faster because inherited properties are copied.
    Objects may copy properties from any number of prototypes.

    Inheriting from Multiple Prototypes

    This is an important feature because it proves that prototypal inheritance is more powerful than classical inheritance in Java and as powerful as classical inheritance in C++. To implement multiple inheritance in the prototypal pattern you only need to modify the extend function to copy the properties of multiple prototypes: