Inheriting from built-in objects

M

Michael Winter

This is in IE 6...

I'm trying to inherit from built-in JS objects - Array, specifically.
However, I'm having some difficulties. I can add array elements to
the child object, and when I retrieve them, they're the same as what I
added. The problem is, the 'length' property remains zero no matter
how many elements the child contains:

<pair.js>
function pair_getValue()
{
return this.value;
}

function Pair( key, value )
{
this.key = key;
this.value = value;
}

Pair.prototype.getValue = pair_getValue;
<end of pair.js>

<map.js>
function map_add( key, value )
{
if( null != this.findKey( key )) return false;

this[ this.getSize() ] = new Pair( key, value );
// this.getSize() will return 0 - ignore for now!

return true;
}

function map_findKey( key )
{
// returns array index of key or null if not found
}

function map_getSize()
{
return this.length;
}

function map_getValue( key )
{
var i = this.findKey( key );

if( null == i ) return null;
return this[ i ].getValue();
}

function Map
{
}

Map.prototype = new Array();
Map.prototype.add = map_add;
Map.prototype.findKey = map_findKey;
Map.prototype.getSize = map_getSize;
Map.prototype.getValue = map_getValue;
<end of map.js>

<example>
var test = new Map();
test.add( 'some unique key', 'some value' );
test.getValue( 'some unique key' ); // Returns 'some value'
test.getSize(); // Returns 0 (zero)?!?
<end of example>

I also tried setting the 'this.length' property explicitly. The value
persists in the function where it was set, but returns to zero
afterwards. Does this have anything to do with it being native code?

The point of this map is to make using cookies easier (the full Map
object can parse strings) by making the contents atomic. This means
another object: Cookie. This inherits from Map. This brings another
problem: both objects have 'serialize' functions. Map concatenates
the key/value pairs using a given separator and the equals character.
Cookie then appends the 'expires', 'path', 'domain' and 'secure'
fields (if set) to the Map values. So far, I've used this structure:

function cookie_serialize()
{
var temp;

// ******************************************
temp = this.base.prototype.serialize();
// ******************************************
if( this.domain ) temp = temp + ';DOMAIN=' + this.domain;
// Date.toGMTString() was depreciated in v1.3
// and just calls Date.toUDTString()
if( this.expires ) temp = temp + ';EXPIRES=' +
this.expires.toUDTString();
if( this.path ) temp = temp + ';PATH=' + this.path;
if( this.secure ) temp = temp + ';SECURE';
return temp;
}

function Cookie()
{
this.base = Map;
// Set property defaults...
}

Cookie.prototype = new Map();
Cookie.prototype.serialize = cookie_serialize();

It works: Map.serialize (map_serialize) is called, but is it correct?
Why doesn't this.base.serialize() work?

Thanks in advance,
Mike
 
D

Douglas Crockford

I'm trying to inherit from built-in JS objects - Array, specifically.
However, I'm having some difficulties. I can add array elements to
the child object, and when I retrieve them, they're the same as what I
added. The problem is, the 'length' property remains zero no matter
how many elements the child contains:
I also tried setting the 'this.length' property explicitly. The value
persists in the function where it was set, but returns to zero
afterwards. Does this have anything to do with it being native code?

Stick with objects if you can. You can't inherit array-ness. You can inherit the
values of a particular array. As you are discovering, that does not buy you very
much.

However, you can add methods to all arrays. For example,

Array.method('sum', function (s) {
if (!isNumber(s)) {
s = 0;
}
for (var i = 0; i < this.length; ++i) {
s += this;
}
return s;
});

var ten = [0, 1, 2, 3, 4].sum();

This adds a sum method to all arrays. (For the 'method' method, see
http://www.crockford.com/javascript/inheritance.html)
 
M

Michael Winter

on 11/11/2003:
code?

Stick with objects if you can. You can't inherit array-ness. You can inherit the
values of a particular array. As you are discovering, that does not buy you very
much.

I can appreciate that. Upon reflection, I don't think that Map, as an
array, would be very useful. It would have been in my original
implementation, but not so much now.

What about method overriding, and explicitly calling overridden parent
methods. Is this the proper way to go about it?

function map_serialize()
{
return 'some-string';
}

function Map
{
}

Map.prototype.serialize = map_serialize;

function cookie_serialize()
{
// Want to call Map.serialize() here:
this.parent.prototype.serialize(); // returns 'some-string' OK, but
correct?
}

function Cookie
{
this.parent = Map;
}

Cookie.prototype = new Map();
Cookie.prototype.serialize = cookie_serialize;

I'm also looking for an explanation as to how the Map object
referenced by Cookie.parent and Cookie.prototype are the same. This
approach is shown in the Client-side JavaScript Guide (v1.3), but no
reasoning is given. I'm not complaining that it works, just curious
why.

Mike
 
D

Douglas Crockford

Stick with objects if you can. You can't inherit array-ness.
I can appreciate that. Upon reflection, I don't think that Map, as an
array, would be very useful. It would have been in my original
implementation, but not so much now.

What about method overriding, and explicitly calling overridden parent
methods. Is this the proper way to go about it?

Check out the uber function in
http://www.crockford.com/javascript/inheritance.html

But caution: That is old-school thinking. Calling super classes in fine for
static languages, but this is a very dynamic language. Open your mind to the
many forms of object augmentation.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,076
Latest member
OrderKetoBeez

Latest Threads

Top