Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript inheritance idea (part 2)

Okay, my first attempt at trying to explain what I was doing failed miserably. I'm basically copying Crockford's Object.create(), except with private variables.

If you look at the accepted answer here How to inherit from a class in javascript?, you will see Object.create as the last pattern, which I think better fits the prototypal nature of Javascript (objects beget objects) instead of emulating classical inheritance (classes beget objects).

If you look at Wikipedia's article on prototype based programming (http://en.wikipedia.org/wiki/Prototype-based_programming), you can see more of what I mean.

The drawback with Object.create() though is that there is no support for private members. This is what I propose:

Function.prototype.from = function(obj) {
    function F() {this.parent = Object(obj);}
    F.prototype = obj;
    var out = new F();
    this.apply(out);
    return out;
};

Then, you create objects as thus:

// Create an object
var a = function() {
    var private_property = 'blue';
    this.public_property = 7;

    this.public_method = function() {
        alert(this.public_property + ' ' + private_property);
    }
}.from(null); // .from() works too, but .from(null) is more revealing


// Create a new object using 'a' as the prototype
var b = function() {
    var private_property = 'red';
    this.public_property = 8;
}.from(a);


// See the results
a.public_method(); // Alerts '7 blue'
b.public_method(); // Alerts '8 blue' - Parent methods use parent private variables

a.public_method = function() { alert('rabbit'); };

a.public_method(); // Alerts 'rabbit'
b.public_method(); // Alerts 'rabbit'

b.public_method = function() { alert('dog'); };

a.public_method(); // Alerts 'rabbit'
b.public_method(); // Alerts 'dog' - Parent method is overwritten

The way I made the "from" function is such that when a parent object changes its methods, if you want to prevent the change in a child instance, you can specify:

this.public_method = this.parent.public_method;

in the child instance.

Note also that objects created ex nihilo do not inherit from Object (hasOwnProperty, etc..). You must explicitly specify this as .from(Object).

Benefits of this pattern:

  1. Memory is not wasted for each new instance
  2. It adheres to a true prototypal inheritance pattern
  3. You have access to the parent object using this.parent (this.__proto__ is browser specific)
  4. Private variables now exist

There is one major drawback of this method that I can think of: the 'function()' syntax may confuse people into thinking a function is assigned to the variable instead of an object.

My question is, are there other drawbacks that I am missing? (Don't include drawbacks of the prototypal pattern--that's subjective--but only of my implementation).

like image 489
Nick Avatar asked Jul 31 '10 00:07

Nick


People also ask

What is JavaScript inheritance?

The JavaScript inheritance is a mechanism that allows us to create new classes on the basis of already existing classes. It provides flexibility to the child class to reuse the methods and variables of a parent class. The JavaScript extends keyword is used to create a child class on the basis of a parent class.

What are the types of inheritance in JavaScript?

Mainly there are three types of inheritance in JavaScript. They are, prototypal, pseudo classical, and functional.

How can I get multiple inheritance in JavaScript?

An object can be inherited from multiple other objects, i.e. the object has common property from other parent objects not only a single parent. In JavaScript, this can be achieved by merging properties from different properties into one single object.

How does prototypal inheritance work?

The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the [[Prototype]] of an object, we use Object. getPrototypeOf and Object.


1 Answers

First, as already mentioned, the Function.prototype approach is really a pain. Why not implement the same thing like this:

Object.createChild = function(obj, constructor) {
    function F() { this.parent = Object(obj); }
    F.prototype = obj;
    var out = new F();
    if (typeof constructor == 'function') {
        constructor.apply(out);
    }
    return out;
};

Then use

var a = Object.createChild(null, function () { /*...*/ });
var b = Object.createChild(a, function () { /*...*/ });

with the same results as above. Bonus: You can omit the constructor argument, like this:

var c = Object.createChild(anything);

Second, I don't know if there's any use for true prototypal inheritance, as you call it. In real life, I'm pretty sure the constructor function is particularly tailored to the object that's about to be extended (a). Thus, you're gonna end up calling

var x = f.from(a);
var y = f.from(a);

with the very same f-a combination over and over again. And yes, you save some bytes of memory as compared to a class-driven approach, but honestly, who cares?

Still, the whole thing is a really good idea in theory.

like image 57
user123444555621 Avatar answered Oct 18 '22 07:10

user123444555621