2
\$\begingroup\$

I'm reading a book called JavaScript Web Applications. In first chapter, it introduces an implementation of class library. Here's an intermediate version:

var Class = function () {
    var klass = function () {
        this.init.apply(this, arguments);
    }
    klass.prototype.init = function (args) {};

    // Adding class properties
    klass.extend = function (obj) {
        var extended = obj.extended;
        for (var i in obj) {
            klass[i] = obj[i];
        }
        if (extended) extended(klass);
    };

    // Adding instance propertied
    klass.include = function (obj) {
        var included = obj.included;
        for (var i in obj) {
            klass.prototype[i] = obj[i];
        }
        if (included) include(klass)
    };

    return klass;
}

Then it can be used like this:

var Person = new Class;
Person.extend({
    find: function (id) { /* ... */ }
});
var person = Person.find(1);

var Person = new Class;
Person.include({
    save: function () { /* ... */ }
});
var person = new Person;
person.save();

I modified it to that it support non-shared instance properties, and here's my version:

var Class = function (properties) {
    var klass = function () {
        this.init.apply(this, arguments);
    }
    klass.prototype.init = function (args) {
        var self = this;
        if (properties instanceof Array && typeof args === 'object') {
            properties.forEach(function (p) {
                if (typeof args[p] !== 'undefined') {
                    self[p] = args[p];
                }
            });
        }
    };

    // extend and include

    return klass;
}

So it can be used like this:

var Person = new Class(['name', 'age'];
var person = new Person({ name: 'bob', age: '30' });

Is my approach ok? I also wonder that why Person.name was "" in my approach? I expected it to be undefined.

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

There is nothing fundamentally wrong about your class strategy, it is a matter of personal style really. The only suggestion I would have is to add Object.prototype.hasOwnProperty guards in the for-in loops, to avoid extending your classes with bogus properties if someone adds things to Object.prototype.

for (var i in obj) {
     if(Object.prototype.hasOwnProperty.call(obj, i)){
         // ...
     }
}

As for the name === '' thing, its just a coincidence since Javascript functions (and therefore your class) always have this property defined:

(function(){}).name     // ""
(function foo(){}).name // "foo"

Some other properties such as "prototype" or "length" should also always be defined and there is nothing you can do about them.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.