<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://wbex.ru/index.php?action=history&amp;feed=atom&amp;title=JavaScript_Tutorial%2FObject_Oriented%2FInheritance</id>
		<title>JavaScript Tutorial/Object Oriented/Inheritance - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://wbex.ru/index.php?action=history&amp;feed=atom&amp;title=JavaScript_Tutorial%2FObject_Oriented%2FInheritance"/>
		<link rel="alternate" type="text/html" href="http://wbex.ru/index.php?title=JavaScript_Tutorial/Object_Oriented/Inheritance&amp;action=history"/>
		<updated>2026-04-29T16:48:06Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://wbex.ru/index.php?title=JavaScript_Tutorial/Object_Oriented/Inheritance&amp;diff=8465&amp;oldid=prev</id>
		<title>Admin: 1 версия</title>
		<link rel="alternate" type="text/html" href="http://wbex.ru/index.php?title=JavaScript_Tutorial/Object_Oriented/Inheritance&amp;diff=8465&amp;oldid=prev"/>
				<updated>2010-05-26T08:24:19Z</updated>
		
		<summary type="html">&lt;p&gt;1 версия&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr style=&quot;vertical-align: top;&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;Версия 08:24, 26 мая 2010&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; style=&quot;text-align: center;&quot; lang=&quot;ru&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(нет различий)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>http://wbex.ru/index.php?title=JavaScript_Tutorial/Object_Oriented/Inheritance&amp;diff=8464&amp;oldid=prev</id>
		<title> в 18:52, 25 мая 2010</title>
		<link rel="alternate" type="text/html" href="http://wbex.ru/index.php?title=JavaScript_Tutorial/Object_Oriented/Inheritance&amp;diff=8464&amp;oldid=prev"/>
				<updated>2010-05-25T18:52:56Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Adding new properties and methods to the child class==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;All new properties and methods must be added after the line that deletes the new method.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function BaseClass(sColor) {&lt;br /&gt;
    this.color = sColor;&lt;br /&gt;
    this.sayColor = function () {&lt;br /&gt;
        alert(this.color);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function SubClass(sColor, sName) {&lt;br /&gt;
    this.newMethod = BaseClass;&lt;br /&gt;
    this.newMethod(sColor);&lt;br /&gt;
    delete this.newMethod;&lt;br /&gt;
    this.name = sName;&lt;br /&gt;
    this.sayName = function () {&lt;br /&gt;
        alert(this.name);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
var objA = new BaseClass(&amp;quot;red&amp;quot;);&lt;br /&gt;
var objB = new SubClass(&amp;quot;blue&amp;quot;, &amp;quot;MyName&amp;quot;);&lt;br /&gt;
objA.sayColor();&lt;br /&gt;
objB.sayColor();&lt;br /&gt;
objB.sayName();&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== All new properties and methods of the subclass must come after the assignment of the prototype property==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function SubClass() {&lt;br /&gt;
}&lt;br /&gt;
SubClass.prototype = new BaseClass();&lt;br /&gt;
SubClass.prototype.name = &amp;quot;&amp;quot;;&lt;br /&gt;
SubClass.prototype.sayName = function () {&lt;br /&gt;
    alert(this.name);&lt;br /&gt;
};&lt;br /&gt;
var objA = new BaseClass();&lt;br /&gt;
var objB = new SubClass();&lt;br /&gt;
objA.color = &amp;quot;red&amp;quot;;&lt;br /&gt;
objB.color = &amp;quot;blue&amp;quot;;&lt;br /&gt;
objB.name = &amp;quot;MyName&amp;quot;;&lt;br /&gt;
objA.sayColor();&lt;br /&gt;
objB.sayColor();&lt;br /&gt;
objB.sayName();&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Class Inheritance==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;Inheritance&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
function Song(title,type) {&lt;br /&gt;
   this.title = title;&lt;br /&gt;
   this.type = type;&lt;br /&gt;
   this.getTitle=function() {&lt;br /&gt;
      return &amp;quot;Song: &amp;quot; + this.title + &amp;quot; Type: &amp;quot; + this.type;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
function SubSong(title,type,artist) {&lt;br /&gt;
   this.artist = artist;&lt;br /&gt;
   this.toString(&amp;quot;Artist is &amp;quot; + artist);&lt;br /&gt;
   Song.apply(this,arguments);&lt;br /&gt;
   this.toString = function () {&lt;br /&gt;
     return &amp;quot;Artist: &amp;quot; + this.artist + &amp;quot; &amp;quot; + this.getTitle();&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
SubSong.prototype = new Song();&lt;br /&gt;
var song = new SubSong(&amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;, &amp;quot;Artist&amp;quot;);&lt;br /&gt;
alert(song.toString());&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Hybrid Method for class inheritance==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;In the SubClass constructor, object masquerading is used to inherit the color property from BaseClass.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Then prototype chaining is used to inherit the methods of BaseClass.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function BaseClass(sColor) {&lt;br /&gt;
    this.color = sColor;&lt;br /&gt;
}&lt;br /&gt;
BaseClass.prototype.sayColor = function () {&lt;br /&gt;
    alert(this.color);&lt;br /&gt;
};&lt;br /&gt;
function SubClass(sColor, sName) {&lt;br /&gt;
    BaseClass.call(this, sColor);&lt;br /&gt;
    this.name = sName;&lt;br /&gt;
}&lt;br /&gt;
SubClass.prototype = new BaseClass();&lt;br /&gt;
SubClass.prototype.sayName = function () {&lt;br /&gt;
    alert(this.name);&lt;br /&gt;
};&lt;br /&gt;
var objA = new BaseClass(&amp;quot;red&amp;quot;);&lt;br /&gt;
var objB = new SubClass(&amp;quot;blue&amp;quot;, &amp;quot;MyName&amp;quot;);&lt;br /&gt;
objA.sayColor();&lt;br /&gt;
objB.sayColor();&lt;br /&gt;
objB.sayName();&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Inheritance==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Call the constructor from base class&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;A constructor assigns all properties and methods using the this keyword.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;You can make the constructor of BaseClass into a method of SubClass and call it.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;After the calling, subClass receives the properties and methods defined in BaseClass&amp;quot;s constructor.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;In the following code, the &amp;quot;newMethod&amp;quot; is assigned to BaseClass.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Then, the &amp;quot;newMethod&amp;quot; is called, passing the color argument from the SubClass constructor.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;The final line of code deletes the reference to BaseClass so that it cannot be called later on.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function BaseClass(sColor) {&lt;br /&gt;
    this.color = sColor;&lt;br /&gt;
    this.sayColor = function () {&lt;br /&gt;
        alert(this.color);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
function SubClass(sColor) {&lt;br /&gt;
    this.newMethod = BaseClass;&lt;br /&gt;
    this.newMethod(sColor);&lt;br /&gt;
    delete this.newMethod;&lt;br /&gt;
}&lt;br /&gt;
var objA = new BaseClass(&amp;quot;red&amp;quot;);&lt;br /&gt;
var objB = new SubClass(&amp;quot;blue&amp;quot;);&lt;br /&gt;
objA.sayColor();&lt;br /&gt;
objB.sayColor();&lt;br /&gt;
objB.sayName();&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Prototype Chaining==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The downside to prototype chaining is that it has no support for multiple inheritance.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Prototype chaining involves overwriting the prototype property of the class with another type of object.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;You can set the prototype property of SubClass to be an instance of BaseClass to inherit all the properties and methods of BaseClass.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function BaseClass() {&lt;br /&gt;
}&lt;br /&gt;
BaseClass.prototype.color = &amp;quot;red&amp;quot;;&lt;br /&gt;
BaseClass.prototype.sayColor = function () {&lt;br /&gt;
    alert(this.color);&lt;br /&gt;
};&lt;br /&gt;
function SubClass() {&lt;br /&gt;
}&lt;br /&gt;
SubClass.prototype = new BaseClass();&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== The Apply() Method==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The apply() method takes two arguments.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;The first one is the object to be used for this.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;The second one is an array of arguments to be passed to the function.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function sayColor(sPrefix, sSuffix) {&lt;br /&gt;
    alert(sPrefix + this.color + sSuffix);&lt;br /&gt;
};&lt;br /&gt;
var obj = new Object();&lt;br /&gt;
obj.color = &amp;quot;red&amp;quot;;&lt;br /&gt;
sayColor.apply(obj, new Array(&amp;quot;The color is &amp;quot;,&amp;quot;, a very nice color indeed.&amp;quot;));&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== The Call() Method==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The first argument of the Call() Method is the object to be used for &amp;quot;this&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;All other arguments are passed directly to the function itself.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function sayColor(sPrefix, sSuffix) {&lt;br /&gt;
    alert(sPrefix + this.color + sSuffix);&lt;br /&gt;
};&lt;br /&gt;
var obj = new Object();&lt;br /&gt;
obj.color = &amp;quot;red&amp;quot;;&lt;br /&gt;
sayColor.call(obj, &amp;quot;The color is &amp;quot;, &amp;quot;, a very nice color indeed. &amp;quot;);&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Three-level inheritance==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;Example&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
function Shape(iSides) {&lt;br /&gt;
    this.sides  = iSides;&lt;br /&gt;
    if (typeof Shape._initialized == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
        Shape.prototype.getArea = function () {&lt;br /&gt;
            return 0;&lt;br /&gt;
        };&lt;br /&gt;
        Shape._initialized = true;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
function Triangle(iBase, iHeight) {&lt;br /&gt;
    Shape.call(this, 3);&lt;br /&gt;
    this.base = iBase;&lt;br /&gt;
    this.height = iHeight;&lt;br /&gt;
    if (typeof Triangle._initialized == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
        Triangle.prototype.getArea = function () {&lt;br /&gt;
            return 0.5 * this.base * this.height;&lt;br /&gt;
        };&lt;br /&gt;
        Triangle._initialized = true;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
Triangle.prototype = new Shape();&lt;br /&gt;
function Rectangle(iLength, iWidth) {&lt;br /&gt;
    Shape.call(this, 4);&lt;br /&gt;
    this.length = iLength;&lt;br /&gt;
    this.width = iWidth;&lt;br /&gt;
    if (typeof Rectangle._initialized == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
        Rectangle.prototype.getArea = function () {&lt;br /&gt;
            return this.length * this.width;&lt;br /&gt;
        };&lt;br /&gt;
        Rectangle._initialized = true;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
Rectangle.prototype = new Shape();&lt;br /&gt;
&lt;br /&gt;
var triangle = new Triangle(12, 4);&lt;br /&gt;
var rectangle = new Rectangle(22, 10);&lt;br /&gt;
document.write(&amp;quot;triangle.sides:&amp;quot;+triangle.sides);&lt;br /&gt;
document.write(&amp;quot;&amp;lt;BR&amp;gt;&amp;quot;);&lt;br /&gt;
document.write(&amp;quot;triangle.getArea():&amp;quot;+triangle.getArea());&lt;br /&gt;
document.write(&amp;quot;&amp;lt;BR&amp;gt;&amp;quot;);&lt;br /&gt;
document.write(&amp;quot;rectangle.sides:&amp;quot;+rectangle.sides);&lt;br /&gt;
document.write(&amp;quot;&amp;lt;BR&amp;gt;&amp;quot;);&lt;br /&gt;
document.write(&amp;quot;rectangle.getArea():&amp;quot;+rectangle.getArea());&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Three level inheritance by using the Hybrid Method==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function Shape(iSides) {&lt;br /&gt;
    this.sides = iSides;&lt;br /&gt;
}&lt;br /&gt;
Shape.prototype.getArea = function (ss) {&lt;br /&gt;
    return 0;&lt;br /&gt;
};&lt;br /&gt;
function Triangle(iBase, iHeight) {&lt;br /&gt;
    Shape.call(this, 3);&lt;br /&gt;
    this.base = iBase;&lt;br /&gt;
    this.height = iHeight;&lt;br /&gt;
}&lt;br /&gt;
Triangle.prototype = new Shape();&lt;br /&gt;
Triangle.prototype.getArea = function () {&lt;br /&gt;
    return 0.5 * this.base * this.height;&lt;br /&gt;
};&lt;br /&gt;
function Rectangle(iLength, iWidth) {&lt;br /&gt;
    Shape.call(this, 4);&lt;br /&gt;
    this.length = iLength;&lt;br /&gt;
    this.width = iWidth;&lt;br /&gt;
}&lt;br /&gt;
Rectangle.prototype = new Shape();&lt;br /&gt;
Rectangle.prototype.getArea = function () {&lt;br /&gt;
    return this.length * this.width;&lt;br /&gt;
};&lt;br /&gt;
var triangle = new Triangle(12, 4);&lt;br /&gt;
var rectangle = new Rectangle(22, 10);&lt;br /&gt;
alert(triangle.sides);        //outputs &amp;quot;3&amp;quot;&lt;br /&gt;
alert(triangle.getArea());    //outputs &amp;quot;24&amp;quot;&lt;br /&gt;
alert(rectangle.sides);       //outputs &amp;quot;4&amp;quot;&lt;br /&gt;
alert(rectangle.getArea());   //outputs &amp;quot;220&amp;quot;&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Using apply function to call base constructor==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;Example&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
function BaseClass(sColor) {&lt;br /&gt;
    this.color = sColor;&lt;br /&gt;
    this.sayColor = function () {&lt;br /&gt;
        alert(this.color);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
function SubClass(sColor, sName) {&lt;br /&gt;
    BaseClass.apply(this, arguments);&lt;br /&gt;
    this.name = sName;&lt;br /&gt;
    this.sayName = function () {&lt;br /&gt;
        alert(this.name);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
var objA = new BaseClass(&amp;quot;red&amp;quot;);&lt;br /&gt;
var objB = new SubClass(&amp;quot;blue&amp;quot;, &amp;quot;MyName&amp;quot;);&lt;br /&gt;
objA.sayColor();&lt;br /&gt;
objB.sayColor();&lt;br /&gt;
objB.sayName();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Using &amp;quot;apply method&amp;quot; to call the constructor of the base class==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function BaseClass(sColor) {&lt;br /&gt;
    this.color = sColor;&lt;br /&gt;
    this.sayColor = function () {&lt;br /&gt;
        alert(this.color);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
function SubClass(sColor, sName) {&lt;br /&gt;
    BaseClass.apply(this, new Array(sColor));&lt;br /&gt;
    this.name = sName;&lt;br /&gt;
    this.sayName = function () {&lt;br /&gt;
        alert(this.name);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
var objA = new BaseClass(&amp;quot;red&amp;quot;);&lt;br /&gt;
var objB = new SubClass(&amp;quot;blue&amp;quot;, &amp;quot;MyName&amp;quot;);&lt;br /&gt;
objA.sayColor();&lt;br /&gt;
objB.sayColor();&lt;br /&gt;
objB.sayName();&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Using call function to call the constructor from base class==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;Example&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
function BaseClass(sColor) {&lt;br /&gt;
    this.color = sColor;&lt;br /&gt;
    this.sayColor = function () {&lt;br /&gt;
        alert(this.color);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
function SubClass(sColor, sName) {&lt;br /&gt;
    BaseClass.call(this, sColor);&lt;br /&gt;
    this.name = sName;&lt;br /&gt;
    this.sayName = function () {&lt;br /&gt;
        alert(this.name);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
var objA = new BaseClass(&amp;quot;red&amp;quot;);&lt;br /&gt;
var objB = new SubClass(&amp;quot;blue&amp;quot;, &amp;quot;MyName&amp;quot;);&lt;br /&gt;
objA.sayColor();&lt;br /&gt;
objB.sayColor();&lt;br /&gt;
objB.sayName();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Using &amp;quot;call method&amp;quot; to call the constructor of base class==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function BaseClass(sColor) {&lt;br /&gt;
    this.color = sColor;&lt;br /&gt;
    this.sayColor = function () {&lt;br /&gt;
        alert(this.color);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
function SubClass(sColor, sName) {&lt;br /&gt;
    BaseClass.call(this, sColor);&lt;br /&gt;
    this.name = sName;&lt;br /&gt;
    this.sayName = function () {&lt;br /&gt;
        alert(this.name);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
var objA = new BaseClass(&amp;quot;red&amp;quot;);&lt;br /&gt;
var objB = new SubClass(&amp;quot;blue&amp;quot;, &amp;quot;MyName&amp;quot;);&lt;br /&gt;
objA.sayColor();&lt;br /&gt;
objB.sayColor();&lt;br /&gt;
objB.sayName();&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Using xbObjects to build three-level inheritance==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;Example&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * xbObjects.js&lt;br /&gt;
 * $Revision: 1.2 $ $Date: 2003/02/07 16:04:20 $&lt;br /&gt;
 */&lt;br /&gt;
/* ***** BEGIN LICENSE BLOCK *****&lt;br /&gt;
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1&lt;br /&gt;
 *&lt;br /&gt;
 * The contents of this file are subject to the Mozilla Public License Version&lt;br /&gt;
 * 1.1 (the &amp;quot;License&amp;quot;); you may not use this file except in compliance with&lt;br /&gt;
 * the License. You may obtain a copy of the License at&lt;br /&gt;
 * http://www.mozilla.org/MPL/&lt;br /&gt;
 *&lt;br /&gt;
 * Software distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; basis,&lt;br /&gt;
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License&lt;br /&gt;
 * for the specific language governing rights and limitations under the&lt;br /&gt;
 * License.&lt;br /&gt;
 *&lt;br /&gt;
 * The Original Code is Bob Clary code.&lt;br /&gt;
 *&lt;br /&gt;
 * The Initial Developer of the Original Code is&lt;br /&gt;
 * Bob Clary.&lt;br /&gt;
 * Portions created by the Initial Developer are Copyright (C) 2000&lt;br /&gt;
 * the Initial Developer. All Rights Reserved.&lt;br /&gt;
 *&lt;br /&gt;
 * Contributor(s): Bob Clary &amp;lt;bc@bclary.ru&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * ***** END LICENSE BLOCK ***** */&lt;br /&gt;
/*&lt;br /&gt;
ChangeLog: 2001-12-19 - bclary - changed xbException init method to&lt;br /&gt;
           remove possible exception due to permission denied issues&lt;br /&gt;
           in gecko 0.9.5+&lt;br /&gt;
*/&lt;br /&gt;
function _Classes()&lt;br /&gt;
{&lt;br /&gt;
  if (typeof(_classes) != &amp;quot;undefined&amp;quot;)&lt;br /&gt;
    throw(&amp;quot;Only one instance of _Classes() can be created&amp;quot;);&lt;br /&gt;
  function registerClass(className, parentClassName)&lt;br /&gt;
  {&lt;br /&gt;
    if (!className)&lt;br /&gt;
      throw(&amp;quot;xbObjects.js:_Classes::registerClass: className missing&amp;quot;);&lt;br /&gt;
    if (className in _classes)&lt;br /&gt;
      return;&lt;br /&gt;
    if (className != &amp;quot;xbObject&amp;quot; &amp;amp;&amp;amp; !parentClassName)&lt;br /&gt;
      parentClassName = &amp;quot;xbObject&amp;quot;;&lt;br /&gt;
    if (!parentClassName)&lt;br /&gt;
      parentClassName = null;&lt;br /&gt;
    else if ( !(parentClassName in _classes))&lt;br /&gt;
      throw(&amp;quot;xbObjects.js:_Classes::registerClass: parentClassName &amp;quot; + parentClassName + &amp;quot; not defined&amp;quot;);&lt;br /&gt;
    // evaluating and caching the prototype object in registerClass&lt;br /&gt;
    // works so long as we are dealing with &amp;quot;normal&amp;quot; source files&lt;br /&gt;
    // where functions are created in the global context and then&lt;br /&gt;
    // statements executed. when evaling code blocks as in xbCOM,&lt;br /&gt;
    // this no longer works and we need to defer the prototype caching&lt;br /&gt;
    // to the defineClass method&lt;br /&gt;
    _classes[className] = { &amp;quot;classConstructor&amp;quot;: null, &amp;quot;parentClassName&amp;quot;: parentClassName };&lt;br /&gt;
  }&lt;br /&gt;
  _Classes.prototype.registerClass = registerClass;&lt;br /&gt;
  function defineClass(className, prototype_func)&lt;br /&gt;
  {&lt;br /&gt;
    var p;&lt;br /&gt;
    if (!className)&lt;br /&gt;
      throw(&amp;quot;xbObjects.js:_Classes::defineClass: className not given&amp;quot;);&lt;br /&gt;
    var classRef = _classes[className];&lt;br /&gt;
    if (!classRef)&lt;br /&gt;
      throw(&amp;quot;xbObjects.js:_Classes::defineClass: className &amp;quot; + className + &amp;quot; not registered&amp;quot;);&lt;br /&gt;
    if (classRef.classConstructor)&lt;br /&gt;
      return;&lt;br /&gt;
    classRef.classConstructor = eval( className );&lt;br /&gt;
    var childPrototype  = classRef.classConstructor.prototype;&lt;br /&gt;
    var parentClassName = classRef.parentClassName;&lt;br /&gt;
    if (parentClassName)&lt;br /&gt;
    {&lt;br /&gt;
      var parentClassRef = _classes[parentClassName];&lt;br /&gt;
      if (!parentClassRef)&lt;br /&gt;
        throw(&amp;quot;xbObjects.js:_Classes::defineClass: parentClassName &amp;quot; + parentClassName + &amp;quot; not registered&amp;quot;);&lt;br /&gt;
      if (!parentClassRef.classConstructor)&lt;br /&gt;
      {&lt;br /&gt;
        // force parent&amp;quot;s prototype to be created by creating a dummy instance&lt;br /&gt;
        // note constructor must handle &amp;quot;default&amp;quot; constructor case&lt;br /&gt;
        var dummy;&lt;br /&gt;
        eval(&amp;quot;dummy = new &amp;quot; + parentClassName + &amp;quot;();&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      var parentPrototype = parentClassRef.classConstructor.prototype;&lt;br /&gt;
      for (p in parentPrototype)&lt;br /&gt;
      {&lt;br /&gt;
        switch (p)&lt;br /&gt;
        {&lt;br /&gt;
        case &amp;quot;isa&amp;quot;:&lt;br /&gt;
        case &amp;quot;classRef&amp;quot;:&lt;br /&gt;
        case &amp;quot;parentPrototype&amp;quot;:&lt;br /&gt;
        case &amp;quot;parentConstructor&amp;quot;:&lt;br /&gt;
        case &amp;quot;inheritedFrom&amp;quot;:&lt;br /&gt;
          break;&lt;br /&gt;
        default:&lt;br /&gt;
          childPrototype[p] = parentPrototype[p];&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    prototype_func();&lt;br /&gt;
    childPrototype.isa        = className;&lt;br /&gt;
    childPrototype.classRef   = classRef;&lt;br /&gt;
    // cache method implementor info&lt;br /&gt;
    childPrototype.inheritedFrom = new Object();&lt;br /&gt;
    if (parentClassName)&lt;br /&gt;
    {&lt;br /&gt;
      for (p in parentPrototype)&lt;br /&gt;
      {&lt;br /&gt;
        switch (p)&lt;br /&gt;
        {&lt;br /&gt;
        case &amp;quot;isa&amp;quot;:&lt;br /&gt;
        case &amp;quot;classRef&amp;quot;:&lt;br /&gt;
        case &amp;quot;parentPrototype&amp;quot;:&lt;br /&gt;
        case &amp;quot;parentConstructor&amp;quot;:&lt;br /&gt;
        case &amp;quot;inheritedFrom&amp;quot;:&lt;br /&gt;
          break;&lt;br /&gt;
        default:&lt;br /&gt;
          if (childPrototype[p] == parentPrototype[p] &amp;amp;&amp;amp; parentPrototype.inheritedFrom[p])&lt;br /&gt;
          {&lt;br /&gt;
            childPrototype.inheritedFrom[p] = parentPrototype.inheritedFrom[p];&lt;br /&gt;
          }&lt;br /&gt;
          else&lt;br /&gt;
          {&lt;br /&gt;
            childPrototype.inheritedFrom[p] = parentClassName;&lt;br /&gt;
          }&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  _Classes.prototype.defineClass = defineClass;&lt;br /&gt;
}&lt;br /&gt;
// create global instance&lt;br /&gt;
var _classes = new _Classes();&lt;br /&gt;
// register root class xbObject&lt;br /&gt;
_classes.registerClass(&amp;quot;xbObject&amp;quot;);&lt;br /&gt;
function xbObject()&lt;br /&gt;
{&lt;br /&gt;
  _classes.defineClass(&amp;quot;xbObject&amp;quot;, _prototype_func);&lt;br /&gt;
  this.init();&lt;br /&gt;
  function _prototype_func()&lt;br /&gt;
  {&lt;br /&gt;
    // isa is set by defineClass() to the className&lt;br /&gt;
    // Note that this can change dynamically as the class is cast&lt;br /&gt;
    // into it&amp;quot;s ancestors...&lt;br /&gt;
    xbObject.prototype.isa        = null;&lt;br /&gt;
    // classref is set by defineClass() to point to the&lt;br /&gt;
    // _classes entry for this class. This allows access&lt;br /&gt;
    // the original _class&amp;quot;s entry no matter how it has&lt;br /&gt;
    // been recast.&lt;br /&gt;
    // *** This will never change!!!! ***&lt;br /&gt;
    xbObject.prototype.classRef      = null;&lt;br /&gt;
    xbObject.prototype.inheritedFrom = new Object();&lt;br /&gt;
    function init() { }&lt;br /&gt;
    xbObject.prototype.init        = init;&lt;br /&gt;
    function destroy() {}&lt;br /&gt;
    xbObject.prototype.destroy      = destroy;&lt;br /&gt;
    function parentMethod(method, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)&lt;br /&gt;
    {&lt;br /&gt;
      // find who implemented this method&lt;br /&gt;
      var className       = this.isa;&lt;br /&gt;
      var parentClassName = _classes[className].classConstructor.prototype.inheritedFrom[method];&lt;br /&gt;
      var tempMethod      = _classes[parentClassName].classConstructor.prototype[method];&lt;br /&gt;
      // &amp;quot;cast&amp;quot; this into the implementor of the method&lt;br /&gt;
      // so that if parentMethod is called by the parent&amp;quot;s method,&lt;br /&gt;
      // the search for it&amp;quot;s implementor will start there and not&lt;br /&gt;
      // cause infinite recursion&lt;br /&gt;
      this.isa   = parentClassName;&lt;br /&gt;
      var retVal = tempMethod.call(this, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);&lt;br /&gt;
      this.isa   = className;&lt;br /&gt;
      return retVal;&lt;br /&gt;
    }&lt;br /&gt;
    xbObject.prototype.parentMethod    = parentMethod;&lt;br /&gt;
    function isInstanceOf(otherClassConstructor)&lt;br /&gt;
    {&lt;br /&gt;
      var className = this.isa;&lt;br /&gt;
      var otherClassName = otherClassConstructor.prototype.isa;&lt;br /&gt;
      while (className)&lt;br /&gt;
      {&lt;br /&gt;
        if (className == otherClassName)&lt;br /&gt;
          return true;&lt;br /&gt;
        className = _classes[className].parentClassName;&lt;br /&gt;
      }&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
    xbObject.prototype.isInstanceOf    = isInstanceOf;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
// eof: xbObjects.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
_classes.registerClass(&amp;quot;Shape&amp;quot;);&lt;br /&gt;
function Shape(iSides) {&lt;br /&gt;
    _classes.defineClass(&amp;quot;Shape&amp;quot;, prototypeFunction);&lt;br /&gt;
    this.init(iSides);&lt;br /&gt;
    function prototypeFunction() {&lt;br /&gt;
        Shape.prototype.init = function(iSides) {&lt;br /&gt;
            this.parentMethod(&amp;quot;init&amp;quot;);&lt;br /&gt;
            this.sides = iSides;&lt;br /&gt;
        };&lt;br /&gt;
        Shape.prototype.getArea = function () {&lt;br /&gt;
            return 0;&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
_classes.registerClass(&amp;quot;Triangle&amp;quot;, &amp;quot;Shape&amp;quot;);&lt;br /&gt;
function Triangle(iBase, iHeight) {&lt;br /&gt;
    _classes.defineClass(&amp;quot;Triangle&amp;quot;, prototypeFunction);&lt;br /&gt;
    this.init(iBase,iHeight);&lt;br /&gt;
    function prototypeFunction() {&lt;br /&gt;
        Triangle.prototype.init = function(iBase, iHeight) {&lt;br /&gt;
            this.parentMethod(&amp;quot;init&amp;quot;, 3);&lt;br /&gt;
            this.base = iBase;&lt;br /&gt;
            this.height = iHeight;&lt;br /&gt;
        };&lt;br /&gt;
        Triangle.prototype.getArea = function () {&lt;br /&gt;
            return 0.5 * this.base * this.height;&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
_classes.registerClass(&amp;quot;Rectangle&amp;quot;, &amp;quot;Shape&amp;quot;);&lt;br /&gt;
function Rectangle(iLength, iWidth) {&lt;br /&gt;
    _classes.defineClass(&amp;quot;Rectangle&amp;quot;, prototypeFunction);&lt;br /&gt;
    this.init(iLength, iWidth);&lt;br /&gt;
    function prototypeFunction() {&lt;br /&gt;
        Rectangle.prototype.init = function(iLength, iWidth) {&lt;br /&gt;
            this.parentMethod(&amp;quot;init&amp;quot;, 4);&lt;br /&gt;
            this.length = iLength;&lt;br /&gt;
            this.width = iWidth;&lt;br /&gt;
        }&lt;br /&gt;
        Rectangle.prototype.getArea = function () {&lt;br /&gt;
            return this.length * this.width;&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
var triangle = new Triangle(10, 40);&lt;br /&gt;
var rectangle = new Rectangle(20, 50);&lt;br /&gt;
alert(triangle.sides);&lt;br /&gt;
alert(triangle.getArea());&lt;br /&gt;
alert(rectangle.sides);&lt;br /&gt;
alert(rectangle.getArea());&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
== Using xbObjects to call the function from base class==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;Example&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * xbObjects.js&lt;br /&gt;
 * $Revision: 1.2 $ $Date: 2003/02/07 16:04:20 $&lt;br /&gt;
 */&lt;br /&gt;
/* ***** BEGIN LICENSE BLOCK *****&lt;br /&gt;
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1&lt;br /&gt;
 *&lt;br /&gt;
 * The contents of this file are subject to the Mozilla Public License Version&lt;br /&gt;
 * 1.1 (the &amp;quot;License&amp;quot;); you may not use this file except in compliance with&lt;br /&gt;
 * the License. You may obtain a copy of the License at&lt;br /&gt;
 * http://www.mozilla.org/MPL/&lt;br /&gt;
 *&lt;br /&gt;
 * Software distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; basis,&lt;br /&gt;
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License&lt;br /&gt;
 * for the specific language governing rights and limitations under the&lt;br /&gt;
 * License.&lt;br /&gt;
 *&lt;br /&gt;
 * The Original Code is Bob Clary code.&lt;br /&gt;
 *&lt;br /&gt;
 * The Initial Developer of the Original Code is&lt;br /&gt;
 * Bob Clary.&lt;br /&gt;
 * Portions created by the Initial Developer are Copyright (C) 2000&lt;br /&gt;
 * the Initial Developer. All Rights Reserved.&lt;br /&gt;
 *&lt;br /&gt;
 * Contributor(s): Bob Clary &amp;lt;bc@bclary.ru&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * ***** END LICENSE BLOCK ***** */&lt;br /&gt;
/*&lt;br /&gt;
ChangeLog: 2001-12-19 - bclary - changed xbException init method to&lt;br /&gt;
           remove possible exception due to permission denied issues&lt;br /&gt;
           in gecko 0.9.5+&lt;br /&gt;
*/&lt;br /&gt;
function _Classes()&lt;br /&gt;
{&lt;br /&gt;
  if (typeof(_classes) != &amp;quot;undefined&amp;quot;)&lt;br /&gt;
    throw(&amp;quot;Only one instance of _Classes() can be created&amp;quot;);&lt;br /&gt;
  function registerClass(className, parentClassName)&lt;br /&gt;
  {&lt;br /&gt;
    if (!className)&lt;br /&gt;
      throw(&amp;quot;xbObjects.js:_Classes::registerClass: className missing&amp;quot;);&lt;br /&gt;
    if (className in _classes)&lt;br /&gt;
      return;&lt;br /&gt;
    if (className != &amp;quot;xbObject&amp;quot; &amp;amp;&amp;amp; !parentClassName)&lt;br /&gt;
      parentClassName = &amp;quot;xbObject&amp;quot;;&lt;br /&gt;
    if (!parentClassName)&lt;br /&gt;
      parentClassName = null;&lt;br /&gt;
    else if ( !(parentClassName in _classes))&lt;br /&gt;
      throw(&amp;quot;xbObjects.js:_Classes::registerClass: parentClassName &amp;quot; + parentClassName + &amp;quot; not defined&amp;quot;);&lt;br /&gt;
    // evaluating and caching the prototype object in registerClass&lt;br /&gt;
    // works so long as we are dealing with &amp;quot;normal&amp;quot; source files&lt;br /&gt;
    // where functions are created in the global context and then&lt;br /&gt;
    // statements executed. when evaling code blocks as in xbCOM,&lt;br /&gt;
    // this no longer works and we need to defer the prototype caching&lt;br /&gt;
    // to the defineClass method&lt;br /&gt;
    _classes[className] = { &amp;quot;classConstructor&amp;quot;: null, &amp;quot;parentClassName&amp;quot;: parentClassName };&lt;br /&gt;
  }&lt;br /&gt;
  _Classes.prototype.registerClass = registerClass;&lt;br /&gt;
  function defineClass(className, prototype_func)&lt;br /&gt;
  {&lt;br /&gt;
    var p;&lt;br /&gt;
    if (!className)&lt;br /&gt;
      throw(&amp;quot;xbObjects.js:_Classes::defineClass: className not given&amp;quot;);&lt;br /&gt;
    var classRef = _classes[className];&lt;br /&gt;
    if (!classRef)&lt;br /&gt;
      throw(&amp;quot;xbObjects.js:_Classes::defineClass: className &amp;quot; + className + &amp;quot; not registered&amp;quot;);&lt;br /&gt;
    if (classRef.classConstructor)&lt;br /&gt;
      return;&lt;br /&gt;
    classRef.classConstructor = eval( className );&lt;br /&gt;
    var childPrototype  = classRef.classConstructor.prototype;&lt;br /&gt;
    var parentClassName = classRef.parentClassName;&lt;br /&gt;
    if (parentClassName)&lt;br /&gt;
    {&lt;br /&gt;
      var parentClassRef = _classes[parentClassName];&lt;br /&gt;
      if (!parentClassRef)&lt;br /&gt;
        throw(&amp;quot;xbObjects.js:_Classes::defineClass: parentClassName &amp;quot; + parentClassName + &amp;quot; not registered&amp;quot;);&lt;br /&gt;
      if (!parentClassRef.classConstructor)&lt;br /&gt;
      {&lt;br /&gt;
        // force parent&amp;quot;s prototype to be created by creating a dummy instance&lt;br /&gt;
        // note constructor must handle &amp;quot;default&amp;quot; constructor case&lt;br /&gt;
        var dummy;&lt;br /&gt;
        eval(&amp;quot;dummy = new &amp;quot; + parentClassName + &amp;quot;();&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      var parentPrototype = parentClassRef.classConstructor.prototype;&lt;br /&gt;
      for (p in parentPrototype)&lt;br /&gt;
      {&lt;br /&gt;
        switch (p)&lt;br /&gt;
        {&lt;br /&gt;
        case &amp;quot;isa&amp;quot;:&lt;br /&gt;
        case &amp;quot;classRef&amp;quot;:&lt;br /&gt;
        case &amp;quot;parentPrototype&amp;quot;:&lt;br /&gt;
        case &amp;quot;parentConstructor&amp;quot;:&lt;br /&gt;
        case &amp;quot;inheritedFrom&amp;quot;:&lt;br /&gt;
          break;&lt;br /&gt;
        default:&lt;br /&gt;
          childPrototype[p] = parentPrototype[p];&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    prototype_func();&lt;br /&gt;
    childPrototype.isa        = className;&lt;br /&gt;
    childPrototype.classRef   = classRef;&lt;br /&gt;
    // cache method implementor info&lt;br /&gt;
    childPrototype.inheritedFrom = new Object();&lt;br /&gt;
    if (parentClassName)&lt;br /&gt;
    {&lt;br /&gt;
      for (p in parentPrototype)&lt;br /&gt;
      {&lt;br /&gt;
        switch (p)&lt;br /&gt;
        {&lt;br /&gt;
        case &amp;quot;isa&amp;quot;:&lt;br /&gt;
        case &amp;quot;classRef&amp;quot;:&lt;br /&gt;
        case &amp;quot;parentPrototype&amp;quot;:&lt;br /&gt;
        case &amp;quot;parentConstructor&amp;quot;:&lt;br /&gt;
        case &amp;quot;inheritedFrom&amp;quot;:&lt;br /&gt;
          break;&lt;br /&gt;
        default:&lt;br /&gt;
          if (childPrototype[p] == parentPrototype[p] &amp;amp;&amp;amp; parentPrototype.inheritedFrom[p])&lt;br /&gt;
          {&lt;br /&gt;
            childPrototype.inheritedFrom[p] = parentPrototype.inheritedFrom[p];&lt;br /&gt;
          }&lt;br /&gt;
          else&lt;br /&gt;
          {&lt;br /&gt;
            childPrototype.inheritedFrom[p] = parentClassName;&lt;br /&gt;
          }&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  _Classes.prototype.defineClass = defineClass;&lt;br /&gt;
}&lt;br /&gt;
// create global instance&lt;br /&gt;
var _classes = new _Classes();&lt;br /&gt;
// register root class xbObject&lt;br /&gt;
_classes.registerClass(&amp;quot;xbObject&amp;quot;);&lt;br /&gt;
function xbObject()&lt;br /&gt;
{&lt;br /&gt;
  _classes.defineClass(&amp;quot;xbObject&amp;quot;, _prototype_func);&lt;br /&gt;
  this.init();&lt;br /&gt;
  function _prototype_func()&lt;br /&gt;
  {&lt;br /&gt;
    // isa is set by defineClass() to the className&lt;br /&gt;
    // Note that this can change dynamically as the class is cast&lt;br /&gt;
    // into it&amp;quot;s ancestors...&lt;br /&gt;
    xbObject.prototype.isa        = null;&lt;br /&gt;
    // classref is set by defineClass() to point to the&lt;br /&gt;
    // _classes entry for this class. This allows access&lt;br /&gt;
    // the original _class&amp;quot;s entry no matter how it has&lt;br /&gt;
    // been recast.&lt;br /&gt;
    // *** This will never change!!!! ***&lt;br /&gt;
    xbObject.prototype.classRef      = null;&lt;br /&gt;
    xbObject.prototype.inheritedFrom = new Object();&lt;br /&gt;
    function init() { }&lt;br /&gt;
    xbObject.prototype.init        = init;&lt;br /&gt;
    function destroy() {}&lt;br /&gt;
    xbObject.prototype.destroy      = destroy;&lt;br /&gt;
    function parentMethod(method, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)&lt;br /&gt;
    {&lt;br /&gt;
      // find who implemented this method&lt;br /&gt;
      var className       = this.isa;&lt;br /&gt;
      var parentClassName = _classes[className].classConstructor.prototype.inheritedFrom[method];&lt;br /&gt;
      var tempMethod      = _classes[parentClassName].classConstructor.prototype[method];&lt;br /&gt;
      // &amp;quot;cast&amp;quot; this into the implementor of the method&lt;br /&gt;
      // so that if parentMethod is called by the parent&amp;quot;s method,&lt;br /&gt;
      // the search for it&amp;quot;s implementor will start there and not&lt;br /&gt;
      // cause infinite recursion&lt;br /&gt;
      this.isa   = parentClassName;&lt;br /&gt;
      var retVal = tempMethod.call(this, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);&lt;br /&gt;
      this.isa   = className;&lt;br /&gt;
      return retVal;&lt;br /&gt;
    }&lt;br /&gt;
    xbObject.prototype.parentMethod    = parentMethod;&lt;br /&gt;
    function isInstanceOf(otherClassConstructor)&lt;br /&gt;
    {&lt;br /&gt;
      var className = this.isa;&lt;br /&gt;
      var otherClassName = otherClassConstructor.prototype.isa;&lt;br /&gt;
      while (className)&lt;br /&gt;
      {&lt;br /&gt;
        if (className == otherClassName)&lt;br /&gt;
          return true;&lt;br /&gt;
        className = _classes[className].parentClassName;&lt;br /&gt;
      }&lt;br /&gt;
      return false;&lt;br /&gt;
    }&lt;br /&gt;
    xbObject.prototype.isInstanceOf    = isInstanceOf;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
// eof: xbObjects.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
_classes.registerClass(&amp;quot;BaseClass&amp;quot;);&lt;br /&gt;
function BaseClass(sColor) {&lt;br /&gt;
    _classes.defineClass(&amp;quot;BaseClass&amp;quot;, prototypeFunction);&lt;br /&gt;
    this.init(sColor);&lt;br /&gt;
    function prototypeFunction() {&lt;br /&gt;
        BaseClass.prototype.init = function (sColor) {&lt;br /&gt;
            this.parentMethod(&amp;quot;init&amp;quot;);&lt;br /&gt;
            this.color = sColor;&lt;br /&gt;
        };&lt;br /&gt;
        BaseClass.prototype.sayColor = function () {&lt;br /&gt;
            alert(this.color);&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
var objA = new BaseClass(&amp;quot;red&amp;quot;);&lt;br /&gt;
objA.sayColor();   &lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
			</entry>

	</feed>