AS1 OOP: Controlling OOP
         by senocular  

__constructor__
The tradition of double underscore padded variables continues with the __constructor__ property. The final of the 3 ‘automatic’ properties in instances, __constructor__ is a property referencing the constructor of a class instance primarily for use by the super operator. Basically its more or less a repeat of the constructor property. However, its purpose is not to tell you what the constructor of an instance is, but rather to tell super what the constructor is. As such, __constructor__ is more of a prototype object property. All class instances have them, but those in use by the super operator are those in prototype objects (where super looks to figure out what your instance’s class constructor is).

Just as any object instance looks to its own __proto__ for the next shared object in its inheritance chain, super uses __constructor__ to find an instance’s constructor. Super, however, doesn’t use the instance’s own __constructor__ property, it uses the instance’s class prototype __constructor__ property, or to that instance, its __proto__.__constructor__. After all, the instance’s constructor is not the super class constructor. Its still its own constructor. The instance’s class prototype’s constructor, however, would be the instances super class constructor. So it’s there the super must look.

You can think of these double underscore properties as road signs, pointing in the direction of prototype objects and constructors.

[ __proto__ and __constructor__ as pointing signs ]

These road signs, however, are for internal use only. So they’re more along the lines of road signs in a secret military base. Luckily for us, we know where that base is and can sneak in during nights to change those signs around.

A quick example of switching those signs, or at least __constructor__, can be seen with email. Because email has certain common elements that you would find with any other type of more general mail, things like a recipient and a message, it can be made as a subclass of a mail super class. As a subclass of mail, email would need its instances to have mail properties defined for them when created, thus super is utilized to provide that. But what if some sneaky advertiser came in and changed e-mail's __constructor__ property

Spam = function(){
this.to = "everyone in your address book";
this.message = "ENLARGE YOURSELF BY 200%!";
};

 
Mail = function(recipient, message){
this.recipient = recipient;
this.message = message;
};
Email = function(subject, recipient, message){
this.subject = subject;
super(recipient, message); // uses __constructor__
};
Email.prototype = new Mail();

 
myMail = new Email("greetings", "you", "hello! your friend, xxx");
trace(myMail.subject); // greetings
trace(myMail.recipient); // you
trace(myMail.message); // hello! your friend, xxx

 
// change email’s __constructor__ and witness the results
Email.prototype.__constructor__ = Spam;

 
myMail = new Email("greetings", "you", "hello! your friend, xxx");
trace(myMail.subject); // greetings
trace(myMail.recipient); // everyone in your address book
trace(myMail.message); // ENLARGE YOURSELF BY 200%!

You can see what happened with super after the email.prototype.__constructor__ was changed from pointing to its default of mail to instead the spam function. The super call no longer saw mail as being the super class of email, it saw spam as the super class, and as such, the definitions provided by spam were added into the myMail instance within the constructor call.

Note that inheritance was established for the prior example. For classes not inheriting from other classes, you have no __constructor__ property in the class’s prototype. Because its an instance property, it’s assigned from the instance created in establishing inheritance with a new super class defined as the prototype object. Default prototype obejcts are without __constructor__ properties but, they do have constructor properties, and they reference the class constructor function.

MyClass = function(){};
trace(MyClass.prototype.__constructor__); // traces undefined
trace(MyClass.prototype.constructor); // traces [type Function]
trace(MyClass.prototype.constructor == MyClass); // traces true

Similarly, the constructor function itself, as a Function object instance, also is without a __constructor__ property.

MyClass = function(){}
trace(MyClass.__constructor__); // traces undefined
trace(MyClass.constructor); // traces [type Function]
trace(MyClass.constructor == Function); // traces true

With anything you create using the new keyword, though, you can be confident that it will have a __constructor__ property.

 

Prev Page
 



SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.