5
\$\begingroup\$

I built an easy inheritance implementation for JavScript that works similar to other OO languages and wanted some feedback on it. This works perfectly how I'd like it to, but I've read a lot of varying opinions about using __proto__ and was wondering if there's a better way to do this.

jsFiddle

/**
 *
 * Extensible Prototype
 *
 */
Object.prototype.extends = function(obj){
        this.__proto__ = new obj;

        return this;
};  

/**
 *
 * Parent Object
 *
 */
var Person = function(name){

        this.name = name;

        this.sayName = function(){
                alert(this.name);
        };

        return this;
};

/**
 *
 * Child Object
 *
 */
var Programmer = function(name){
        this.extends(Person);

        this.name = name;
        this.title = "Software Engineer";

        this.sayTitle = function(){
                alert(this.title);
        };
};

var eric = new Programmer('eric');
eric.sayName();
eric.sayTitle();
\$\endgroup\$
  • 1
    \$\begingroup\$ You can avoid __proto__ by using Object.create \$\endgroup\$ – elclanrs Aug 27 '14 at 0:26
1
\$\begingroup\$

Not really that bad, unless you consider the fact that __proto__ is non-standard (but is used in most browsers). While some developers argue that __proto__ isn't going away soon, I'd rather go for a more "standard-ish" approach.

The usual way is to just use prototypes like they were designed:

// Person class
var Person = function(){
  this.foo = 'hello';
  this.bar = 'world';
};
Person.prototype = Object.create(Object.prototype);
// Since we just clobbered prototype, we return the constructor
Person.prototype.constructor = Person;
// Add in methods
Person.prototype.read = function(){/*...*/};

// Programmer class
var Programmer = function(){
  // This is to run this object through the parent constructor so that it gets the properties.
  Person.apply(this,arguments);

  this.right = 'bob';
  this.left = 'alice';
};

// Then "inherit" the parent methods
Programmer.prototype = Object.create(Person.prototype);
Programmer.prototype.constructor = Programmer;
Programmer.prototype.readCode = function(){/*...*/};

console.log(new Person());
console.log(new Programmer());

Now it's pretty ceremonious at this point, all that prototype stuff. You can skip all that if you create functions that automate that. Some libraries do the same thing, with sugar:

var ChildClass = BaseClass.extend();

One problem with this style of encapsulation is that your methods are defined per instance rather than shared. This will eat up memory:

function Class(){
  this.foo = function(){};
}

var instance1 = new Class();
var instance2 = new Class();
console.log(instance1.foo === instance2.foo); // false

Sometimes "forcing" private properties are just more hassle than originally intended. Besides, using the dev tools, your code is open to modification anyways. What most libraries do is use "pseudo-private", by prefixing the property with _. Technically, these properties are public, but it's a common programming convention telling the developer it's private.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I guess my main concern with the "standard" way of handling inheritance is that it loses the feeling of being truly encapsulated. It feels strange creating and object from the outside inward instead of inside of itself. Especially when it comes to readability and portability. Any thoughts on this? \$\endgroup\$ – Eric Uldall Aug 27 '14 at 19:18
  • \$\begingroup\$ I would also mention extending OBject.prototype the way he does \$\endgroup\$ – megawac Aug 29 '14 at 19:19
  • \$\begingroup\$ The way who does, @megawac Your comment is a bit vague...sorry. Not trying to be difficult, just discerning your meaning. \$\endgroup\$ – Eric Uldall Sep 3 '14 at 0:55
  • \$\begingroup\$ The way OP modifies 0bject.prototype is considered nearly as poor a practices as they come in JS \$\endgroup\$ – megawac Sep 3 '14 at 2:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.