JS Getters/Setters on prototype inheritance

810 Views Asked by At

Recently I've written a small library in es6 classes. Now I've decided to rewrite it to es5 code. Because the library was using classes inheritance a lot (class A extends B), I had to write a small piece of code to simulate es6 classes inheritance:

combine.js

module.exports = function () {
    var _arguments = arguments;

    var Class = function () {
        for (var i = 0; i < _arguments.length; i++) {
            if (typeof _arguments[i] === 'function') {
                _arguments[i].call(this);
            }
        }
    }

    var prototype = { };
    for (var i = 0; i < _arguments.length; i++) {
        if (typeof _arguments[i] === 'function') {
            prototype = Object.assign(prototype, _arguments[i].prototype);
        }
    }
    Class.prototype = prototype;

    return Class
}

But as I learned, this code is not able to combine the getters/setters defined on base functions like that:

var combine = require('./combine.js');

function A() {
    this._loading = false;
}

Object.defineProperty(A.prototype, 'loading', {
    get() {
        return this._loading;
    },
    set(value) {
        this._loading = value;
    }
});

function B() { }

B.prototype.isLoading = function () {
    return this._loading;
}

B.prototype.setLoading = function (loading) {
    this._loading = loading;
}

var C = combine(A, B);
var c = new C();

console.log(c.isLoading()); // false
console.log(c.loading); // c.loading is undefined

c.setLoading(true);
console.log(c.isLoading()); // true
console.log(c.loading); // c.loading is undefined

c.loading = false;
console.log(c.isLoading()); // true
console.log(c.loading); // false

Is there a way how to inherit a getters/setters defined on function prototype?

1

There are 1 best solutions below

0
On

So finally, thanks to @Bergi's links, I've came with working prototype of mixin function, which looks like this:

module.exports = function () {

    var _arguments = arguments;

    var Class = function () {
        for (var i = 0; i < _arguments.length; i++) {
            if (typeof _arguments[i] === 'function') {
                _arguments[i].call(this);
            }
        }
    }

    var prototype = { }
    for (var x = 0; x < _arguments.length; x++) {
        if (typeof _arguments[x] === 'function') {
            var properties = Object.getOwnPropertyNames(_arguments[x].prototype);
            for (let y in properties) {
                if (properties[y] != 'constructor') {
                    Object.defineProperty(
                        prototype,
                        properties[y],
                        Object.getOwnPropertyDescriptor(_arguments[x].prototype, properties[y])
                    );
                }
            }
        }
    }
    Class.prototype = prototype;

    return Class;

}