Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copying Javascript getters/setters to another prototype object

// Base class
var Base = function() {
    this._value = 'base';
};
Base.prototype = {
    constructor: Base,
    // By function
    getValue: function() {
        return this._value;
    },
    // By getter
    get value() {
        return this._value;
    }
};

// Sub class extends Base
var Sub = function() {
    this._value = 'sub';
};
Sub.prototype = {
    constructor: Sub
};
// Pass over methods
Sub.prototype.getValue = Base.prototype.getValue;
Sub.prototype.value = Base.prototype.value;

// ---

var mySub = new Sub();
alert(mySub.getValue()); // Returns 'sub'
alert(mySub.value);      // Returns 'undefined'

At first glance it seems that mySub.value should return the same as mySub.getValue(), but as you can see it instead returns undefined. Obviously the getter is not finding the parent scope as the Sub instance (mySub), but rather a non-existent Base instance.

Is there any way around this other than having to assign the same getters onto the new prototype?

like image 637
Ben Avatar asked May 18 '11 03:05

Ben


3 Answers

A more modern solution is to use the Object.defineProperty since it allows getters and setters to be handled without breaking them.

Only problem is that it takes a descriptor object, so instead of manually making one, use the Object.getOwnPropertyDescriptor function to just get it for you.

var BazValue = Object.getOwnPropertyDescriptor(Base.prototype,'value');

Object.defineProperty(Sub.prototype, 'value', BazValue);
like image 186
Saul does Code Avatar answered Oct 21 '22 02:10

Saul does Code


Sub.prototype.__defineGetter__('value', Base.prototype.__lookupGetter__('value'));

Try that.

like image 11
McKayla Avatar answered Oct 21 '22 04:10

McKayla


I think it would work if you assigned

Sub.prototype = new Base()

The issue is that the constructor is never run when you assign it directly from the Base.prototype.value. That value won't exist until you have an instance of the Base class (via new)

This is my typical method for extending Function to achieve inheritance:

Function.prototype.Extend = function(superClass) {
    this.prototype = new superClass();

    this.prototype.getSuperClass = function() {
        return superClass;
    };
    this.getSuperClass = this.prototype.getSuperClass;
    return this;
};

This will properly assign all of the parent classes methods and properties to the child 'class'.

Usage looks like

var Sub = function() {}
Sub.Extend(Base)
like image 6
Alex Mcp Avatar answered Oct 21 '22 04:10

Alex Mcp