473,395 Members | 1,442 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Inheritance using object prototype

Hi all - I'm preparing to dive in to more complex application
development using javascript, and among other things, I'm having a hard
time wrapping my head around an issues regarding "inheritance" using
the prototype property. I realize there are no classes in JS, that code
therefore lives in objects instead of class definitions, and that
"inheritance" must be achieved prototypically and not classically.
That said, on with the code. Say I have an object I wish to use as a
super type:

function SuperA(name) {
this.name = name;
this.alertName = function() { alert(this.name); }
}

It takes a string in the constructor, assigns it to the name property,
and provides a way to display that name in an alert box, via alertName
method. What I've come to learn is that if I want to create a sub type,
I must assign a new instance of the super type to the prototype of the
sub type. Like so:

function SubA(name) {
//sub type properties
}
SubA.prototype = new SuperA();

This works fine in that when I create an instance of SubA, it
effectively inherits everything from SuperA. What I don't understand is
why this doesn't achieve the same effect:

function SubA(name) {
this.prototype = new SuperA(name);
}

This simply assigns an instance of the super type to the prototype of
the sub type instance in construction, yet if I create an instance and
attempt to call the method:

var supa = new SubA('one');
supa.alertName();

I get a JS error stating that supa.alertName is not a function. Note
that if I augment the the latter constructor to show the memebers in
construction:

function SubA(name) {
this.prototype = new SuperA(name);
for(var m in this.prototype) {
alert(m + ": " + typeof(this.prototype[m]) + ": " +
this.prototype[m]);
}
}

I get two alerts; the first being:

name: string: one

and the second:

alertName: function: function() { alert(this.name); }

I'd appreciate any clarity that is offered. Thanks!

Jan 12 '07 #1
6 1847
VK
burningodzi...@gmail.com wrote:
Hi all - I'm preparing to dive in to more complex application
development using javascript, and among other things, I'm having a hard
time wrapping my head around an issues regarding "inheritance" using
the prototype property.
The first thing you have to do is to read and study
"The JScript Type System, Part Two: Prototypes and constructors"
<http://blogs.msdn.com/ericlippert/archive/2003/11/06/53352.aspx>
by Eric Lippert

Up to date this is the only existing online resource where inheritance
in ECMAScript languages explained both correctly and understandably.
I really don't want to spoil the reading :-) but your current problem
arose from the fact that .prototype property _does not_ define
prototype chain for the object it is applied to. It defines prototype
chain for _instances_ created by the given constructor. Search for the
rest in the linked article.

Besides that two other considerations to take into account:
1) Programming in javascript doesn't mean "use prototype only".
Inherited properties and methods are static in Cx sense: it means that
for 100 object instances there will be only one method if it is
inherited over prototype chain. It means that prototype inheritance is
useful only for members where you don't need to store instance-specific
data. If you need members with instance-specific data then use
constructor itself.

2) Code like
function f() {
this.m = function(){alert('Hello');}
}
forms a closure on each invocation. You don't want to form a closure
unless you _want_ to form a closure.

Jan 12 '07 #2

burningodzi...@gmail.com wrote:
Hi all - I'm preparing to dive in to more complex application
development using javascript, and among other things, I'm having a hard
time wrapping my head around an issues regarding "inheritance" using
the prototype property. I realize there are no classes in JS, that code
therefore lives in objects instead of class definitions, and that
"inheritance" must be achieved prototypically and not classically.
That said, on with the code. Say I have an object I wish to use as a
super type:

function SuperA(name) {
this.name = name;
this.alertName = function() { alert(this.name); }
}

It takes a string in the constructor, assigns it to the name property,
and provides a way to display that name in an alert box, via alertName
method. What I've come to learn is that if I want to create a sub type,
I must assign a new instance of the super type to the prototype of the
sub type. Like so:

function SubA(name) {
//sub type properties
}
SubA.prototype = new SuperA();

This works fine in that when I create an instance of SubA, it
effectively inherits everything from SuperA. What I don't understand is
why this doesn't achieve the same effect:

function SubA(name) {
this.prototype = new SuperA(name);
}

This simply assigns an instance of the super type to the prototype of
the sub type instance in construction, yet if I create an instance and
attempt to call the method:

var supa = new SubA('one');
supa.alertName();

I get a JS error stating that supa.alertName is not a function. Note
that if I augment the the latter constructor to show the memebers in
construction:

function SubA(name) {
this.prototype = new SuperA(name);
for(var m in this.prototype) {
alert(m + ": " + typeof(this.prototype[m]) + ": " +
this.prototype[m]);
}
}

I get two alerts; the first being:

name: string: one

and the second:

alertName: function: function() { alert(this.name); }

I'd appreciate any clarity that is offered. Thanks!
Hi

Three points:-

1. In very simple terms, the "prototype" property used for inheritance
must usually be property of the Function you are using as a constructor
function.

When you create an Object with "new SubA", the Object you create does
not itself does not itself give you express access to the "prototype"
used in the inheritance chain through a "prototype" property.

Having said that, in Firefox (and perhaps other browsers, excluding IE)
you can access this prototype through the "__proto__" property. See :
http://www.webreference.com/js/column79/6.html

2. When you when you call "new SubA", the "this" value refers to the
Object you are creating, not the SubA Function.

So

"this.prototype = new SuperA(name);"

effectively creates a new dynamic property, called "prototype", on your
Object; but which has nothing to do with the prototype used in the
inheritance chain.

3. I have no idea what would happen if you called "this.__proto__ =
new SuperA(name)".

Regards

Julian Turner

Jan 12 '07 #3
Thanks for the info - it has been very helpful. VK I digested the
article you liked - it was also quite illuminating - much appreciated.
I have a comment regarding one of your points:
Inherited properties and methods are static in Cx sense: it means that
for 100 object instances there will be only one method if it is
inherited over prototype chain. It means that prototype inheritance is
useful only for members where you don't need to store instance-specific
data. If you need members with instance-specific data then use
constructor itself.
That doesn't seem to be entirely correct - at least not the part about
static in a Cx sense. If I declare a super type with two methods on the
Function:

function SuperA() {}
SuperA.getName = function() { return this.name; }
SuperA.setName = function(n) { this.name = n; }

and then a sub type with this as its prototype:

function SubA(n) {
this.name = typeof(n) == 'undefined' ? '' : n;
}
SubA.prototype = SuperA;

var supa = new SubA('test 1-1');
alert(supa.getName());
supa.setName('test 1-2');
alert(supa.getName());

var supa2 = new SubA('test 2-1');
alert(supa2.getName());
supa2.setName('test 2-2');
alert(supa2.getName());
//verify that 2 different instances have unique data and thus unique
members
alert(supa.getName());

Then the inherited methods act on the instance data, since the methods
access this.name. So in that since they differ from static methods as
they can indeed access instance data (I confirmed creating multiple
instances have unique members). If however the methods are declared
without accessing this.x:

function SuperA() {
this.name = 'super';
}
SuperA.getName = function() { return name; }
SuperA.setName = function(n) { name = n; }

Then the methods all access the singular name property of the SuperA
constructor.

Point being that methods inherited on the prototype chain can access
instance data via this.

Regarding your point on closures - I incorrectly (due to my oo
background) assumed that declaring methods like that would pass them on
to inheriting types. As you pointed out, only members on the Function
prototype get propagated. However it seems that adding methods to the
Function prototype that access instance members via this is a workable
way to pass on methods sub types. Are you under this impression?

Thanks again for the discussion and info!

VK wrote:
burningodzi...@gmail.com wrote:
Hi all - I'm preparing to dive in to more complex application
development using javascript, and among other things, I'm having a hard
time wrapping my head around an issues regarding "inheritance" using
the prototype property.

The first thing you have to do is to read and study
"The JScript Type System, Part Two: Prototypes and constructors"
<http://blogs.msdn.com/ericlippert/archive/2003/11/06/53352.aspx>
by Eric Lippert

Up to date this is the only existing online resource where inheritance
in ECMAScript languages explained both correctly and understandably.
I really don't want to spoil the reading :-) but your current problem
arose from the fact that .prototype property _does not_ define
prototype chain for the object it is applied to. It defines prototype
chain for _instances_ created by the given constructor. Search for the
rest in the linked article.

Besides that two other considerations to take into account:
1) Programming in javascript doesn't mean "use prototype only".
Inherited properties and methods are static in Cx sense: it means that
for 100 object instances there will be only one method if it is
inherited over prototype chain. It means that prototype inheritance is
useful only for members where you don't need to store instance-specific
data. If you need members with instance-specific data then use
constructor itself.

2) Code like
function f() {
this.m = function(){alert('Hello');}
}
forms a closure on each invocation. You don't want to form a closure
unless you _want_ to form a closure.
Jan 12 '07 #4
In article <11**********************@a75g2000cwd.googlegroups .com>,
bu************@gmail.com writes

<snip>
>What I've come to learn is that if I want to create a sub type,
I must assign a new instance of the super type to the prototype of the
sub type. Like so:

function SubA(name) {
//sub type properties
}
SubA.prototype = new SuperA();
<snip>

I'm afraid you've learnt a messy way of doing it.

Suppose you have three constructors A, B, and C, and you want C
instances to derive from B and B from A. When you create a C instance by
doing

var cobj = new C(x, y, z);

you want cobj to have a prototype chain holding all the methods of A, B,
and C objects, and cobj itself to hold all the data fields appropriate
to A, B, and C objects. In javascript you, yourself, have to do the work
of making this happen :-(

The job of the objects in the prototype chain is to hold methods, not
data. To do it cleanly you don't want these objects to be A, B, or C
instances : they are different types. You could call them proto_A,
proto_B, and proto_C instances, and construct them with their own
special constructors.

John
--
John Harris
Jan 12 '07 #5
Hi John - thanks for the comments. Thus far I've learned what you said,
and have been assigning Function definitions (as opposed to instances)
to prototypes of sub types. The one thing that I haven't found that
you've said is that for each instance you must create all it's data
members in the constructor. Following is a snip of code I've been
documenting for my learning purposes - please tell me if feel my
findings are invalid:

function SuperA() {
/*
* Any members defined here will be available to instances created
* via new SuperA(). They are object instance members, NOT Function
* members, and therefore will not be added into the prototype chain
* when SuperA is set as the prototype of other Functions (sub types).
*/
}
/*
* These methods access this.name, and so access the member name
* in the context of the current object instance. This seems to
* effectively allow sub types to inherit these methods and have
* them operate on their instance members.
*
* Note that if a sub type doesn't explicitly declare a this.name
* member in its constructor, the memeber will be undefined. Calling
* [instance].setName on the instance will add this member to it.
*/
SuperA.getName = function() { return this.name; }
SuperA.setName = function(n) { this.name = n; }
/*
* Note that the data member (sname) declared as a Function member of
* SuperA will be propagated to sub type instances. Each sub type
instance
* will have it's own copy (at least of the sname data member), as
proven
* below.
*/
SuperA.sname = 'super';
SuperA.getSname = function() { return this.sname; }
Lastly, regarding your statment:
The job of the objects in the prototype chain is to hold methods, not
data. To do it cleanly you don't want these objects to be A, B, or C
instances : they are different types. You could call them proto_A,
proto_B, and proto_C instances, and construct them with their own
special constructors.
Would you mind providing a simple example?

Much apperciated!
John G Harris wrote:
In article <11**********************@a75g2000cwd.googlegroups .com>,
bu************@gmail.com writes

<snip>
What I've come to learn is that if I want to create a sub type,
I must assign a new instance of the super type to the prototype of the
sub type. Like so:

function SubA(name) {
//sub type properties
}
SubA.prototype = new SuperA();
<snip>

I'm afraid you've learnt a messy way of doing it.

Suppose you have three constructors A, B, and C, and you want C
instances to derive from B and B from A. When you create a C instance by
doing

var cobj = new C(x, y, z);

you want cobj to have a prototype chain holding all the methods of A, B,
and C objects, and cobj itself to hold all the data fields appropriate
to A, B, and C objects. In javascript you, yourself, have to do the work
of making this happen :-(

The job of the objects in the prototype chain is to hold methods, not
data. To do it cleanly you don't want these objects to be A, B, or C
instances : they are different types. You could call them proto_A,
proto_B, and proto_C instances, and construct them with their own
special constructors.

John
--
John Harris
Jan 12 '07 #6
In article <11*********************@38g2000cwa.googlegroups.c om>,
chrislewis <bu************@gmail.comwrites
>Hi John - thanks for the comments. Thus far I've learned what you said,
and have been assigning Function definitions (as opposed to instances)
to prototypes of sub types. The one thing that I haven't found that
you've said is that for each instance you must create all it's data
members in the constructor. Following is a snip of code I've been
documenting for my learning purposes - please tell me if feel my
findings are invalid:

function SuperA() {
/*
* Any members defined here will be available to instances created
* via new SuperA(). They are object instance members, NOT Function
* members, and therefore will not be added into the prototype chain
* when SuperA is set as the prototype of other Functions (sub types).
*/
}
/*
* These methods access this.name, and so access the member name
* in the context of the current object instance. This seems to
* effectively allow sub types to inherit these methods and have
* them operate on their instance members.
*
* Note that if a sub type doesn't explicitly declare a this.name
* member in its constructor, the memeber will be undefined. Calling
* [instance].setName on the instance will add this member to it.
*/
SuperA.getName = function() { return this.name; }
SuperA.setName = function(n) { this.name = n; }
/*
* Note that the data member (sname) declared as a Function member of
* SuperA will be propagated to sub type instances. Each sub type
instance
* will have it's own copy (at least of the sname data member), as
proven
* below.
*/
SuperA.sname = 'super';
SuperA.getSname = function() { return this.sname; }
To tell the truth, I'm not sure what you are trying to say here. Have
you tried drawing a picture of an instance and its prototype chain? Show
where you would like to put the things that are common to all instances,
e.g methods, and where you would like to put the things that can be
different in each instance, e.g data values.

If you have put the same thing in lots of different places, or have
things that are never going to be used, then you've done it in a messy
way.

>Lastly, regarding your statment:
>The job of the objects in the prototype chain is to hold methods, not
data. To do it cleanly you don't want these objects to be A, B, or C
instances : they are different types. You could call them proto_A,
proto_B, and proto_C instances, and construct them with their own
special constructors.

Would you mind providing a simple example?
<URL:http://www.jgharris.demon.co.uk/jsfeats/JSfeats.html#seca1p1>

John
--
John Harris
Jan 13 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Robert Spoons | last post by:
Can you look over this code, preferably try it, and comment? I believe the 'extend' function below will allow you to use full 'class inheritance' in javascript, but I would like to verify it. ...
2
by: stephane | last post by:
Hi all, What I am trying to achieve is an 'inherits' method similar to Douglas Crockford's (http://www.crockford.com/javascript/inheritance.html) but that can enable access to the superclass'...
2
by: Kevin Newman | last post by:
I have been playing around with a couple of ways to add inheritance to a JavaScript singleton pattern. As far as I'm aware, using an anonymous constructor to create a singleton does not allow any...
31
by: John W. Kennedy | last post by:
I quite understand about prototypes and not having classes as such, but I happen to have a problem involving blatant is-a relationships, such that inheritance is the bloody obvious way to go. I can...
14
by: petermichaux | last post by:
Hi, Hopefully the group doesn't mind an(other) inheritance question. Maybe the prototype inheritance style is starting to become a low dim light in my brain...probably not yet. ---- If I...
36
by: Pacific Fox | last post by:
Hi all, haven't posted to this group before, but got an issue I can't work out... and hoping to get some help here ;-) I've got a base object that works fine with named arguments when called...
3
by: linc | last post by:
I am planning on writing a fairly large system in javascript and would like some advice on using the Douglas Crockford 'beget' function to implement prototypal inheritance. Searching the internet...
6
by: howa | last post by:
Consider example: Animal = function(age) { this.age = age; }; Animal.prototype.sleep = function() { alert("Animal Sleeping..."); };
6
by: vwkng1987 | last post by:
Hi everyone Please look at the code below: (I am picking up JS from Crockfold and a few other online sources too) *************************************************************** function...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.