1

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?

Patrik Šimunič
  • 449
  • 1
  • 4
  • 16
  • 1
    "*Now I've decided to rewrite it to es5 code.*" - Why? Let a transpiler do the job for you. – Bergi Jul 16 '17 at 22:48
  • "*`B.prototype.isLoading() { return this._loading; }`*" is a syntax error. If not, throw your internet explorer away. – Bergi Jul 16 '17 at 22:49
  • yeah, thank you, just a mistake in example, this code I don't actually use – Patrik Šimunič Jul 16 '17 at 22:51
  • 1
    That `combine` thing doesn't really do inheritance, it's more like applying mixins. Why don't you just use [proper ES5 class inheritance](https://stackoverflow.com/questions/10898786/correct-javascript-inheritance/)? – Bergi Jul 16 '17 at 22:51
  • 1
    @Bergi is right. Let **Babel** do the work for you (and let IE die of natural causes). Look at [npm](https://www.npmjs.com/), or [bower](https://libraries.io/bower/babel) – M. Davis Jul 16 '17 at 22:53
  • Exact duplicate of [How to assign objects with setters and getters?](https://stackoverflow.com/q/37054596/1048572) or [How to clone a prototype with property methods?](https://stackoverflow.com/q/29298746/1048572) – Bergi Jul 16 '17 at 22:58
  • @M. Davis Of course I could use babel - I'm using babel and I'm letting babel do its work right now. But I just want to get rid of babel and learn how things actually work, since js is not OOP language there is no such thing as "inheritance" like in OOP languages. But if I let babel just "do its magic", I won't fully understand the result code. This is more like experimenting and LEARNING JS IN DEPTH, more then anything. – Patrik Šimunič Jul 16 '17 at 23:06
  • @Bergi Thanks for the link, seems like duplicate. Although I'm not using jQuery, it could work. – Patrik Šimunič Jul 16 '17 at 23:06
  • @PatrikŠimunič Well if you want actual real powerful *inheritance* (not the Java "class" version of it), you should use `Object.create`. Learn about that before getters and setters. – Bergi Jul 16 '17 at 23:09

1 Answers1

0

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;

}
Patrik Šimunič
  • 449
  • 1
  • 4
  • 16