D
Dolaameng
I am reading Nicholas's book <Professional JavaScript for Web
Developers> 2nd. On page 168, he explained the "parasitic constructor
pattern" by an example as follows,
/////////////////////////////////////////////////////
function SpecialArray(){
//create the array
var values = new Array();
//add the values
values.push.apply(values, arguments);
//assign the method
values.toPipedString = function(){
return this.join("|");
};
//return it
return values;
}
var colors = new SpecialArray("red", "blue", "green");
alert(colors.toPipedString()); //"red|blue|green"
/////////////////////////////////////////////////////
The code works perfectly. But I was just wondering if I can implement
the SpecialArray as an inheritance of the built-in Array, using a
classical inheritance pattern. So I came up with two versions of
implementations, which unfortunately, both failed.
My first implementation is like this,
///////////////////My Implementation 1///////////////
function SpecialArray(){
Array.apply(this,arguments);
}
function Temp(){}
Temp.prototype=Array.prototype;
SpecialArray.prorotype=new Temp();
SpecialArray.prototype.constructor=SpecialArray;
SpecialArray.prototype.toPipedString=function(){
return this.join('|');
};
//Test cases
var arr=new SpecialArray(1,2,3);
console.log('constructor: '+arr.constructor); //
Correct: points to SpecialArray
console.log('instanceof specialArray: '+(arr instanceof
SpecialArray)); //Correct: TRUE
console.log('instanceof array: '+(arr instanceof Array)); //
Incorrect: FALSE
console.log('toPipedString: '+arr.toPipedString()); //ERROR:
this.join is not a function
/////////////////////////////////////////////////////
Here my intention was to call the Array constructor in the
SpecialArray constructor, and point SpecialArray's prototype to an
object instantiated by a Temp constructor, whose prototype is set to
be Array's prototype. However the code fails as shown in the commnets
in the testing code beneath.
I suspected that the error was caused by the use of Temp constructor,
so I changed the code and this time I linked the SpecialArray's
prototype directly to an Array instance, like this,
///////////////////My Implementation 2///////////////
function SpecialArray(){
Array.apply(this,arguments);
}
SpecialArray.prorotype=new Array(); //directly linked to an array
instance without Temp
SpecialArray.prototype.constructor=SpecialArray;
SpecialArray.prototype.toPipedString=function(){
return this.join('|');
};
var arr=new SpecialArray(1,2,3);
console.log('constructor: '+arr.constructor); //
Correct: points to SpecialArray
console.log('instanceof specialArray: '+(arr instanceof
SpecialArray)); //Correct: TRUE
console.log('instanceof array: '+(arr instanceof Array)); //
Correct: TRUE
console.log('toPipedString: '+arr.toPipedString()); //
Incorrect: an empty string
/////////////////////////////////////////////////////
This time the testings work fine except that arr.toPipedString()
returns an empty string. I suspect this is because the "this" instance
was not correctly initialized by calling "Array.apply(...)" in
SpecialArray's constructor.
I did a little search online, and found that Array.apply(...) will
RETURN a proper array, but this doesnt help here because we cannot
write the line like
this=Array.apply(null,arguments);
in the constructor, right? Some other guys online also mentioned that
"myClass.apply(something,args) will fail in many cases especially if
called on native classes like Date and Number.". I am not sure of
this.
So somebody please help telling me what was wrong with my code and how
to fix them accordingly? thanks a lot!
Developers> 2nd. On page 168, he explained the "parasitic constructor
pattern" by an example as follows,
/////////////////////////////////////////////////////
function SpecialArray(){
//create the array
var values = new Array();
//add the values
values.push.apply(values, arguments);
//assign the method
values.toPipedString = function(){
return this.join("|");
};
//return it
return values;
}
var colors = new SpecialArray("red", "blue", "green");
alert(colors.toPipedString()); //"red|blue|green"
/////////////////////////////////////////////////////
The code works perfectly. But I was just wondering if I can implement
the SpecialArray as an inheritance of the built-in Array, using a
classical inheritance pattern. So I came up with two versions of
implementations, which unfortunately, both failed.
My first implementation is like this,
///////////////////My Implementation 1///////////////
function SpecialArray(){
Array.apply(this,arguments);
}
function Temp(){}
Temp.prototype=Array.prototype;
SpecialArray.prorotype=new Temp();
SpecialArray.prototype.constructor=SpecialArray;
SpecialArray.prototype.toPipedString=function(){
return this.join('|');
};
//Test cases
var arr=new SpecialArray(1,2,3);
console.log('constructor: '+arr.constructor); //
Correct: points to SpecialArray
console.log('instanceof specialArray: '+(arr instanceof
SpecialArray)); //Correct: TRUE
console.log('instanceof array: '+(arr instanceof Array)); //
Incorrect: FALSE
console.log('toPipedString: '+arr.toPipedString()); //ERROR:
this.join is not a function
/////////////////////////////////////////////////////
Here my intention was to call the Array constructor in the
SpecialArray constructor, and point SpecialArray's prototype to an
object instantiated by a Temp constructor, whose prototype is set to
be Array's prototype. However the code fails as shown in the commnets
in the testing code beneath.
I suspected that the error was caused by the use of Temp constructor,
so I changed the code and this time I linked the SpecialArray's
prototype directly to an Array instance, like this,
///////////////////My Implementation 2///////////////
function SpecialArray(){
Array.apply(this,arguments);
}
SpecialArray.prorotype=new Array(); //directly linked to an array
instance without Temp
SpecialArray.prototype.constructor=SpecialArray;
SpecialArray.prototype.toPipedString=function(){
return this.join('|');
};
var arr=new SpecialArray(1,2,3);
console.log('constructor: '+arr.constructor); //
Correct: points to SpecialArray
console.log('instanceof specialArray: '+(arr instanceof
SpecialArray)); //Correct: TRUE
console.log('instanceof array: '+(arr instanceof Array)); //
Correct: TRUE
console.log('toPipedString: '+arr.toPipedString()); //
Incorrect: an empty string
/////////////////////////////////////////////////////
This time the testings work fine except that arr.toPipedString()
returns an empty string. I suspect this is because the "this" instance
was not correctly initialized by calling "Array.apply(...)" in
SpecialArray's constructor.
I did a little search online, and found that Array.apply(...) will
RETURN a proper array, but this doesnt help here because we cannot
write the line like
this=Array.apply(null,arguments);
in the constructor, right? Some other guys online also mentioned that
"myClass.apply(something,args) will fail in many cases especially if
called on native classes like Date and Number.". I am not sure of
this.
So somebody please help telling me what was wrong with my code and how
to fix them accordingly? thanks a lot!