Oct 10 2008

4

Private Methods with Mootools update(2)

Category: Mutator

UPDATED

I updated my Privates Mutator yet again. Now, if you pass a function into the ‘Privates’ object a bind is created to the class.

Class.Mutators.Privates = function(self,privates){
	self.initalize = (function(){
		for(prop in privates)  this[prop] = ($type(privates[prop]) == 'function') ? privates[prop].bind(self) : privates[prop];
		return self.initialize;
	})();
}

I made a false assumption on how Mutators work within Mootools based on the following code snippet:

            for (var mutator in Class.Mutators){
                if (!this[mutator]) continue;
                Class.Mutators[mutator](this, this[mutator]);
                delete this[mutator];
            }

I was expecting ‘delete this[mutator]‘ to destroy the ‘Privates’ object, it doesn’t!

The ‘delete’ Operator - from “Javascript: The Definitive Guide”

“delete” attempts to delete the object property, array element, or variable specified as its operand. It returns true if the deletion was successful, and false if the operand could not be deleted. If delete is invoked on a nonexistent property, it returns true. Surprisingly, the ECMAScript standard specifies that delete also evaluates to true if the operand is not a property, array element, or variable.

I assume what is happening is ‘this[mutator]‘ is an object property so it should be deleted. It doesn’t get deleted because it is a reference to an object. So the object must be destroyed. The only way to destroy an object in Javascript is to destroy all references to that object.

The following works:

Class.Mutators.Privates = function(self,privates){
    self.initalize = (function(){
        for(prop in privates)
             this[prop] = ($type(privates[prop]) == 'function') ? privates[prop].bind(self) : privates[prop];
        return self.initialize;
    })();
    delete self["Privates"];
    for(prop in privates) delete self["Privates"][prop];
}

Some interesting things to note. Removing ‘delete self["Privates"]‘ fails to work even when this line is called just moments later in the Class Mutators code ( delete this[mutator] ). It must be called before the properties of the ‘Privates’ are deleted.

If I change the last 2 lines to the follow:

	delete self["Privates"];
	privates = null;
	for(prop in privates) delete self["Privates"][prop];

It doesn’t work. Nor does.

        delete this['privates'];
	for(prop in privates) delete privates[prop];

If you have any addition insight into the delete operator or how to elegantly remove object references, please share.

Example:

var Secret = new Class({
	Privates : {
		secret : 'hidden message',
		myFunc : function(){  return this.getSecret(); }
	},
 
	getSecret : function(){
		return secret;
	},
 
	get : function(){
		return myFunc();
	}
});
 
var msg = new Secret();
msg.get(); // returns "hidden message"
msg.Privates.secret; // returns undefined


Oct 10 2008

4

Mootools Singleton Class Mutator

Category: MutatorTags: , ,

I got really excited about Class Mutators within Mootools after reading Jan Kassens blog. If you have ever used Mootools, you have probably seen the standard Mutators. Extends and Implements. These allow you to augment your Classes to help create an inheritance model within Mootools. What I failed to realize is that Mutators goes well beyond that. They have the ability to ‘morph’ your Classes to make your code easier to read and maintain.

I went ahead and implemented the Singleton pattern into Mootools classes.

Class.Mutators.Singleton = function(self,flag){
	if(!flag) return;
	self.constructor.__instance = undefined;
	if($defined(self.initialize) && $type(self.initialize) == 'function') var init = self.initialize;
	self.initialize = function(){
		if(!$defined(this.constructor.__instance)){
			if($defined(init) && $type(init) == 'function') init.apply(this,arguments);
			this.constructor.__instance = this;
		}
		return this.constructor.__instance;
	}
}

Use:

   var Counter = new Class({
         Singleton : true,
 
        initialize : function(){
              this.count = 0;
        },
 
        hit : function(){
             return ++this.count;
       }
  });
 
var a = new Counter();
a.hit(); // returns 1
a.hit(); // return 2
var b = new Counter();
b.hit(); // return 3 !!!

Honestly, this is more for the OO purist out there. I would have to agree with Valerio that the best way to implement a singleton in javascript is to use a basic object. However, I do think that this could be useful in rare occasions.

Tags: , ,