andrea
andrea

Reputation: 61

Adding properties to classes using extend() and include() functions

Can anyone please explain to me what is happening in the following code? I understood the meaning of include() and exclude() but when and why do we use the specific function?

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

    klass.prototype.init = function () {};

    klass.fn = klass.prototype;
    //shortcut to access class
    klass.fn.parent = klass; //where do we use it?

    //adding class properties
    klass.extend = function (obj) {
        var extended = obj.extended; //what is happening here?
        for (var i in obj) {
            klass[i] = obj[i];
        }
        if (extended) extended(klass) //didn't understand this part
    };
    //adding instance properties
    klass.include = function (obj) {
        var included = obj.included; //??
        for (var i in obj) {
            klass.fn[i] = obj[i]; //??
        }
        if (included) included(klass) //??
    };
    return klass;
};
var Person = new Class; // is this same as: var Person = new Class();

Upvotes: 4

Views: 1397

Answers (3)

lazycoder
lazycoder

Reputation: 451

Would like to offer how I understood it. I would break this into two parts: definition, and implementation (or usage). Following the definition that you have quoted above, I would add usage as this code:

var Person = new Class;

Person.extend({
    find: function(id) { /* definition */
    },
    exists: function(id) { /* definition */
    }
});
Person.include({
    save: function(id) { /* definition */
    },
    destroy: function(id) { /* definition */
    }
});

var person_e = Person.find(1);
var person_e = Person.exists(2);

var person = new Person;
person.save();
person.destroy(2);

See this code in continuity with the previous code. I'd try to enumerate what happens:

  1. Class is set to hold the function definition. It isn't executed yet - so Class points to that block in the memory where function definition is written.
  2. var Person = new Class -> This is equivalent to 'new Class()' - so execution of Class happens, and the result is assigned to Person. Since it is invoked with 'new' keyword, 'this' gets assigned to the new instance of Class.
  3. Now, what happens inside Class()? (i) klass is set to function (job of which is initialize 'this' when called) - but not executed just yet. (ii) A init property is defined on klass's prototype; init property is set to an empty function (which we will overwrite later depending upon class we would define) (iii) Some more fancy stuff with extend and include properties on klass (iv) And klass is returned -> klass holds function definition at this point in time. Therefore, calling 'new Class()' returns a function called 'klass' which when called, performs the initialization on 'this'.
  4. Person at this point, in layman terms, can be thought as holding 'function klass()'. So, Person.extend can be thought as to go to klass.extend part of the code. klass.extend is a function which expects an object. This object has key value pairs, key being names of the utilities / functions and values being function definitions. Inside 'for' statement, we do (var i in obj) - so 'i' contains the keys - when we do 'klass.fn[i]' we mean klass.prototype.save or klass.prototype.destroy - since subscript [i] is same as dot notation (namespacing). And we know, methods added to klass.prototype are available to instances of Person, rather than getting added on Person as properties.
  5. We call new Person() - in effect, we are executing klass, since Person holds klass at this point in time, and since new is attached, 'this' is passed. Now, inside 'klass' initialization happens on init property of 'this' (by apply form) -> And this 'init' property we have just overwritten.

    klass.fn.parent = klass; //where do we use it? //no where.

Upvotes: 0

Toomean
Toomean

Reputation: 246

After your question-block author give us this part:

Person.extend({
    extended: function(klass) {
        console.log(klass, " was extended");
    }
});

So if we have an 'extended' property in an argument-object - we call it.

Upvotes: 2

awc737
awc737

Reputation: 889

He got it from Javascript Web Applications by Alex MacCaw. The purpose is to demonstrate implementing Javascript classes, and using proper modularity and inheritance. The author is very abstract in his explanations, and does not specify whether any libraries such as Prototype.js are being used.

I think a good addition to this question would be:

  • Does this all look like native Javascript?
  • Are extend/extended and include/included native methods of Javascript?

Upvotes: 2

Related Questions