Javascript - Prototyping on DOM elements

- 1 answer

Ad

I'm building custom libraries to handle GUI and creating divs and stuff programatically. I also want to extend these objects with children and methods to do something like this:

Function CustomElement() {
  this = document.createElement('div');
  ///--------
  Some custom properties
  ///--------
}

CustomElement.prototype.customMethod = function(args) {
  ///--------
  Some code here
  ///--------
};

var elem = new CustomElement();

document.body.appendChild(elem);

elem.customMethod(args);

I've thoroughly searched for an answer but found none. How can I accomplish this?

Note: I'm posting from my cell phone. Please excuse me if the code looks awful. I'll correct it as soon as I have access to a PC.

Ad

Answer

Ad

I appears you are confused between classical languages such that you are probably use to, and prototypical like languages such as Javascript.

Also, in your example, assigning the value of this is an invalid statement.

In Javascript, instead of creating children of a super class, we create objects that inherit the properties of other objects through the prototype chain. Still with me? This means that your customMethod is not technically a method, rather it is a property called customMethod which has the value of a function object.

Every constructor object (which is just a fancy name for your CustomElement function) has a magical property named prototype as you have discovered. Objects don't have this property, but they do have an implicit reference to their constructor's prototype object. This means you can call your customMethod as if it were a property of elem, but it is really a property of the constructors prototype object. So I guess you could say the prototype object is kind of like a parent and the object is kind of like a child (although this is incorrect terminology). This prototype object may also again have an implicit reference to it's constructor prototype, which may reference it's constructor prototype... and so on. That's why its called the prototype chain.

So to answer your question:

I also want to extend these objects with children and methods... How can I accomplish this?

For a suggestion to emulate child like inheritance, see below. However, your library requires a different approach...

A common angle of attack is to create a constructor which creates a new object, with a new Element object as a property of that object. For example:

function CustomElement(doesLikeTrains) {
    // keep element in this property
    this.nativeElement = document.createElement('div');

    // other properties are separate
    this.likesTrains = doesLikeTrains;
}

// these are also separate 
CustomElement.prototype.doesLikeTrains = function() {
        return this.likesTrains;
};

// Lets make objects!
var elem1 = new CustomElement(true);
var elem2 = new CustomElement(false);

// use object property and inherited properties
// we can still use the element ok
document.body.appendChild(elem2.nativeElement);
elem1.doesLikeTrains(); // prints true
elem2.doesLikeTrains(); // prints false :(

The DOM element assigned to the nativeElement property. This means you may add other properties without changing the native element object, but still have access to them. Both elem1 and elem2 inherit the same doesLikeTrains property with the same value, but each have their own likesTrains property, which is initialised in the constructor, and can keep a value specific to the object instance.

The advantage of this is that you could change the doesLikeTrains function to always return true, and because all objects created using your CustomELement constructor inherit the same prototype, all objects would then like trains regardless!

How would one create children like objects?

To emulate a child structure, consider...

function CustomOtherElement(likesTrains, runsOnCoal) {

    // create new object and inherit from CustomElement
    function EmptyConstructor() {}
    EmptyConstructor.prototype = new CustomElement(likesTrains);

    // add extra stuff to CustomOtherElements only
    EmptyConstructor.runsOnCoal = runsOnCoal;
    EmptyConstructor.isTrainSuperFan = function () {
        return "Hoot hoot, chugga chugga!";
    }

    // return the new object
    return new EmptyConstructor();
}

// now you can do
var elem3 = CustomOtherElement(true, true);
document.body.appendChild(elem3.nativeElement);
elem3.doesLikeTrains(); // true
elem3.isTrainSuperFan(); // "Hoot hoot, chugga chug!"

The above uses this new CustomOtherElement constructor to make an object that inherits CustomeElement and then add some new properties to this new object. Now you can use both the inherited properties from CustomElement and the new ones created on elem3! Happy Javascripting!

Resource: ECMAScript Language Specifications 5.1 section 4.2.1 (Objects)

Ad
source: stackoverflow.com
Ad