Monday, July 23, 2007

Javascript string replacing function (2)

Previously I mentioned a string replacing function that, instead of building a string this way:

tag= '<' + tagname + ' style="background-color:'
+ bgcolor + ';color:' + color + '">' + text + '</' + tagname +'>'

allows for doing it this way:

tag0= '<___ style="background-color:___;color:___">___</___>'
tag1 = tag0._(tagname, bgcolor, color, text, tagname)

or this way :

tag00= '<[.tagname.] style="background-color:[.bgcolor.];'+
'color:[.color.]">[.txt.]</[.tagname.]>'

data = {tagname:'span', bgcolor:'#EEFFBB',color:'red',txt:'tag2'}
tag2 = tag00._(data)


After playing with the regular expression for a while, I come up with a short version :

String.prototype._=function(){
var i=-1, a= arguments
var t= typeof(a[0])=='string'
var rx = t?(/___/g):(/\[\.[A-Za-z0-9_]*\.\]/g)
var f = t?function(x){i++;return a[i]}
:function(x){return a[0][x.slice(2, -2)]||''}
return this.replace(rx,f)
}


To me it's amazing to see how such a task can be accomplished with such a neat code.

Saturday, July 21, 2007

Problems in Javascript Subclassing

In javascript, the subclassing is done this way:
[1] function Person(name, sex){    # Define the superclass
[2] this.name = name
[3] this.sex = sex
[4] this.prn = function(){ return this.name + ', '+ this.sex }
[5] }

[6] function Man(name){ this.sex = 'M' } # Define the subclass
[7] Man.prototype = new Person() # Connect Person and Man

And the instantiation:
[8]  p = new Person('Jane','F')
[9] m = new Man('John')

Checking the function prn (defined in [4]):
p.prn() ==> Jane, F
m.prn() ==> undefined, M


As shown, the name John given to Man when instantiating m ([9]) is NOT transferred to m. It is obvious 'cos we didn't instruct it to do so when defining Man in [6].

Problem.1: Subclass Arguments Are Not Automatically Transferred To Subclass Instances



So, unless explicitly instructed, the arguments of a subclass will not be assigned to the instance of that subclass. That means, [6] needs to be re-defined as:
function Man(name){ 
this.sex = 'M'
this.name= name # <== new line
}

Note that the above highlighted line already exists in the superclass (line [2]). Why does it have to be re-done again in the subclass ? Didn't we already instruct Person to be the super class ?

Problem.2: An Instance of Subclass Is an Instance of the Superclass too ?


Lets investigate the instanceof operator in javascript:
[10] (p instanceof Person)  ==> true
[11] (m instanceof Man) ==> true
[12] (m instanceof Person) ==> true


Line [10] and [11] are what we expect. But [12]? How come m is an instance of Person ? This doesn't sound right.

Problem.3: The Constructor of A Subclass' Instance Is The Superclass But Not the Subclass ?


Check the constructor of the instances of subclass and of superclass:
[13] getConstructor(p) ==> Person
[14] getConstructor(m) ==> Person

Shouldn't the constructor of m be Man?

Solution Proposal



Lets try a new way of defining a subclass. Instead of
function Man(name){ 
this.sex = 'M'
this.name= name # <== new line
}

We try this:
function Woman(name){ update(this, new Person(name, 'F'))}
w= new Woman("Jan")

See the following table for comparison:

ClassesInstanceinstanceof
Person
constructor
function Person(name, sex){
this.name = name
this.sex = sex
this.prn = function(){
return this.name +','+this.sex}
}
ptruePerson
function Man(name){
this.sex = 'M'
this.name= name }
Man.prototype = new Person
mtruePerson
function Woman(name){
update(this, new Person(name,'F'))
}
wfalseWoman

Friday, July 20, 2007

About Subclassing in Javascript

Let the superclass be:
function Person(sex){alert('I am Person')}

and subclasses:

function Man(){this.sex='M'}
function Woman(){this.sex='F'}

The following two subclassing approaches don't seem to make any difference:

Man.prototype = new Person
Woman.prototype = new Person()
m = new Man()
w = new Woman()

In both cases:
  • The function Person will be executed
  • The constructor of both m and w are Person