Nov. 27, 2001

In This Issue

comparison of _prototype and __parent__ chains
 

ISDK/C 4.30e Errata
 

ISDK/C 4.40d Errata
 

ISDK/Java 4.30e Errata

Other Newsletters

DevSpace Developer Support

For more information and resources, visit ScriptEase: ISDK DevSpace online.

Download Center

For latest updates and extensions, visit the ISDK Download Center.

_prototype and __parent__, inheritance and scoping in ECMAScript

A brief description of inheritance and scoping through the _prototype and __parent__ chains.

Our recent Thanksgiving Holiday led me to think about family. When I think about family I think about parents, property, and inheritance. More specifically, I think about ECMAScript inheritance of properties through the __parent__ and _prototype chains. These two types of property chains are often confused, sometimes misused, and too often neglected (like family).

_prototype

The _prototype chain gives ECMAScript class-like behavior, similar to other object-oriented languages. Multiple objects can inherit the same property from a base class object, so that any instance of that class object will inherit the property from the base class. If any instance changes the value of an inherited property the property changes only for that instance, not for the base class or for other objects that inherit from that base class. This is similar to the way basic inheritance acts in any OO language.

__parent__

The __parent__ chains gives an ECMAScript object a way to resolve the location of variable, letting a variable filter down through a hierarchy of sub-objects. Multiple objects can scope to the same property from a base parent object; when any of these objects changes the value of this scoped variable it is changed in the base parent object. This __parent__ chain is unlike inheritance found in most OO languages.

_prototype vs __parent__

These two chains, which are independent of each other, provide a combination that is very useful. Many object in your application may have both types of chains. Because both methods allow an object to reflect data in a base object, implementors sometimes choose one over the other with insufficient thought.

_prototype

The _prototype chain should be selected when you want OO inheritance. That is, when you want to have multiple instances of a base class object inherit the behavior and default values of that base object, and for each instance of that base class object to maintain its own overrides of those inherited defaults. You would use the _prototype chain whenever you define an object that you want other objects to "act like". Additionally, by using the _prototype chain you can have many instance objects inherit lots of properties and methods without using extra memory to duplicate those properties and methods in every instance (important in small-memory situations).

Although a _protoype chain may be created explicitly, it is usually automatically created when the "new" operator is used. With "new", an object's ._prototype is initialized to the .prototype object of the base class.

__parent__

The __parent__ chain should instead be used when you want to represent a hierarchy of objects, where the script in any one object automatically recognizes a variable in an enclosing object. In browsers, for example, the __parent__ chain is how script in a button event may automatically reference a variable in the enclosing form object, or the enclosing frame or document object.

A __parent__ chain is usually created explicitly when designing the hierarchy of your objects. The __parent__ chain is usually ignored unless a function is being called where that function's object has the jseImplicitParents attribute. But you can also tell the interpreter to use the __parent__ chain in a jseInterpret call with the JSE_INTERPRET_IMPLICIT_PARENTS flag, or for all functions by compiling with JSE_ALWAYS_IMPLICIT_PARENTS 1.

Example

The following example demonstrates the order and effect of the different scope chains on objects. For this demo a println() function is assumed, along with the setAttributes() function from the lang library (usually these attributes would be set from your compiled code).

   function demo_func()
   {
      println("init demo_func x = " + x);
      println("init demo_func y = " + y);
      println("init demo_func z = " + z);
   
      x = "demo_func_x";
      y = "demo_func_y";
      z = "demo_func_z";
    
      println("term demo_func x = " + x);
      println("term demo_func y = " + y);
      println("term demo_func z = " + z);
   }
 
   setAttributes(demo_func,IMPLICIT_PARENTS|IMPLICIT_THIS);
 
   var prototype_obj, parent_obj, instance_obj;
 
   prototype_obj = new Object();
   prototype_obj.x = "prototype_x";
   prototype_obj.z = "prototype_z";
   parent_obj = new Object();
   parent_obj.x = "parent_x";
   parent_obj.y = "parent_y";
   parent_obj.z = "parent_z";
 
   instance_obj = new Object();
   instance_obj.z = "instance_z";
   instance_obj._prototype = prototype_obj;
   instance_obj.__parent__ = parent_obj;
   instance_obj.demo_func = demo_func;
 
   println("instance_obj.x = " + instance_obj.x);
   println("instance_obj.y = " + instance_obj.y);
   println("instance_obj.z = " + instance_obj.z);
   println("parent_obj.x = " + parent_obj.x);
   println("parent_obj.y = " + parent_obj.y);
   println("parent_obj.z = " + parent_obj.z);
   println("prototype_obj.x = " + prototype_obj.x);
   println("prototype_obj.y = " + prototype_obj.y);
   println("prototype_obj.z = " + prototype_obj.z);
   println("");
 
   instance_obj.demo_func();
 
   println("");
   println("instance_obj.x = " + instance_obj.x);
   println("instance_obj.y = " + instance_obj.y);
   println("instance_obj.z = " + instance_obj.z);
   println("parent_obj.x = " + parent_obj.x);
   println("parent_obj.y = " + parent_obj.y);
   println("parent_obj.z = " + parent_obj.z);
   println("prototype_obj.x = " + prototype_obj.x);
   println("prototype_obj.y = " + prototype_obj.y);
   println("prototype_obj.z = " + prototype_obj.z);

Executing the above code produces this output:

   instance_obj.x = prototype_x
   instance_obj.y = undefined
   instance_obj.z = instance_z
   parent_obj.x = parent_x
   parent_obj.y = parent_y
   parent_obj.z = parent_z
   prototype_obj.x = prototype_x
   prototype_obj.y = undefined
   prototype_obj.z = prototype_z
   
   init demo_func x = prototype_x
   init demo_func y = parent_y
   init demo_func z = instance_z
   term demo_func x = demo_func_x
   term demo_func y = demo_func_y
   term demo_func z = demo_func_z
   
   instance_obj.x = demo_func_x
   instance_obj.y = undefined
   instance_obj.z = demo_func_z
   parent_obj.x = parent_x
   parent_obj.y = demo_func_y
   parent_obj.z = parent_z
   prototype_obj.x = prototype_x
   prototype_obj.y = undefined
   prototype_obj.z = prototype_z

This code has demonstrated these facts about scoping variables in this implicit-parents / implicit-this function.

  1. When locating a variable V, we first search for this.V, then this._prorotype...V, then this.__parent__...V
  2. When writing to the variable V, if V was located via the _prototype chain then the this object gets a new variable this.V, otherwise the variable V is overwritten that was found in step 1
  3. Inheritance through the __parent__ chain only applies in a function with the jseImplicitParents attribute set.

Related information

  • For a deeper discussion of _prototype and __parent__ see "Appendix D: Advanced Topics / Topic 3" in the ISDK Manuals
  • For a description scoping issues in VoiceXML, see Implementing VoiceXML (VXML).
  • For an example of how _prototype and __parent__ are used in browsers, see the brwsrlib application framework in each ISDK release.

Have a question about how to use ScriptEase:ISDK? Let Dr. Scripter know at http://support.nombasxxx.com/


 Errata

   ISDK/C 4.30e

  • MSVC6 memory allocation bugs: Problems with Microsoft's C++ in Microsoft Visual C++ 6.0, can cause heap allocation errors and memory overwrites that can cause crashes that are extremely erratic and hard to reproduce. [details]

 Errata

   ISDK/C 4.40d

  • MSVC6 memory allocation bugs: Problems with Microsoft's C++ in Microsoft Visual C++ 6.0, can cause heap allocation errors and memory overwrites that can cause crashes that are extremely erratic and hard to reproduce. [Details]

 Errata

   ISDK/Java 4.30e

ScriptEase: ISDK is a product of Nombas, Inc. Visit us at ../index.htm