Inheriting from built-in objects

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Michael Winter

    Inheriting from built-in objects

    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.a dd = map_add;
    Map.prototype.f indKey = map_findKey;
    Map.prototype.g etSize = map_getSize;
    Map.prototype.g etValue = 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_serializ e()
    {
    var temp;

    // *************** *************** ************
    temp = this.base.proto type.serialize( );
    // *************** *************** ************
    if( this.domain ) temp = temp + ';DOMAIN=' + this.domain;
    // Date.toGMTStrin g() was depreciated in v1.3
    // and just calls Date.toUDTStrin g()
    if( this.expires ) temp = temp + ';EXPIRES=' +
    this.expires.to UDTString();
    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.prototyp e = new Map();
    Cookie.prototyp e.serialize = cookie_serializ e();

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

    Thanks in advance,
    Mike

    --
    Michael Winter
    M.Winter@[no-spam]blueyonder.co.u k (remove [no-spam] to reply)


  • Douglas Crockford

    #2
    Re: Inheriting from built-in objects

    > I'm trying to inherit from built-in JS objects - Array, specifically.[color=blue]
    > 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:[/color]
    [color=blue]
    > 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?[/color]

    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('s um', function (s) {
    if (!isNumber(s)) {
    s = 0;
    }
    for (var i = 0; i < this.length; ++i) {
    s += this[i];
    }
    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)

    Comment

    • Michael Winter

      #3
      Re: Inheriting from built-in objects

      "Douglas Crockford" wrote on 11/11/2003:
      [color=blue][color=green]
      > > I'm trying to inherit from built-in JS objects - Array,[/color][/color]
      specifically.[color=blue][color=green]
      > > However, I'm having some difficulties. I can add array elements[/color][/color]
      to[color=blue][color=green]
      > > the child object, and when I retrieve them, they're the same as[/color][/color]
      what I[color=blue][color=green]
      > > added. The problem is, the 'length' property remains zero no[/color][/color]
      matter[color=blue][color=green]
      > > how many elements the child contains:[/color]
      >[color=green]
      > > I also tried setting the 'this.length' property explicitly. The[/color][/color]
      value[color=blue][color=green]
      > > persists in the function where it was set, but returns to zero
      > > afterwards. Does this have anything to do with it being native[/color][/color]
      code?[color=blue]
      >
      > Stick with objects if you can. You can't inherit array-ness. You can[/color]
      inherit the[color=blue]
      > values of a particular array. As you are discovering, that does not[/color]
      buy you very[color=blue]
      > much.[/color]

      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.s erialize = map_serialize;

      function cookie_serializ e()
      {
      // Want to call Map.serialize() here:
      this.parent.pro totype.serializ e(); // returns 'some-string' OK, but
      correct?
      }

      function Cookie
      {
      this.parent = Map;
      }

      Cookie.prototyp e = new Map();
      Cookie.prototyp e.serialize = cookie_serializ e;

      I'm also looking for an explanation as to how the Map object
      referenced by Cookie.parent and Cookie.prototyp e 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

      --
      Michael Winter
      M.Winter@[no-spam]blueyonder.co.u k (remove [no-spam] to reply)


      Comment

      • Douglas Crockford

        #4
        Re: Inheriting from built-in objects

        > > Stick with objects if you can. You can't inherit array-ness.[color=blue][color=green]
        > > You can inherit the values of a particular array.
        > > As you are discovering, that does not buy you very
        > > much.[/color]
        >
        > 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?[/color]

        Check out the uber function in


        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.

        Comment

        Working...