JavaScript: Object Definition Extension

G

Gene Wirchenko

Dear JavaScripters:

The following code is meant is extend an object definition. The
code works. My question is whether it works best. Is the way that I
have initialised the properties in Commercial that are from RealEstate
the best way to do it? I have a feeling that I might/should
initialise them using the RealEstate constructor, but I do not know
how to go about doing that.

1) How should I be doing it?

2) In the template statement, what does the new do? I have seen
code with it and without it. Both seem to work, but which way is
correct/better?

***** Start of Code *****
<html>

<head>
<title>try4.html</title>
</head>

<body>

<script type="text/javascript">

function RealEstate
(
PropertyLocation,
PropertyValue
)
{
this.PropertyLocation=PropertyLocation;
this.PropertyValue=PropertyValue;
}

function Commercial
(
PropertyLocation,
PropertyValue,
PropertyZoning,
PropertyUse
)
{
this.PropertyLocation=PropertyLocation;
this.PropertyValue=PropertyValue;
this.PropertyZoning=PropertyZoning;
this.PropertyUse=PropertyUse;
}

Commercial.template=new RealEstate();

var Prop1=new Commercial("Kamloops",150000,"C-1","light commercial");

document.write("Location: "+Prop1.PropertyLocation+"<br>");
document.write("Value: "+Prop1.PropertyValue+"<br>");
document.write("Zoning: "+Prop1.PropertyZoning+"<br>");
document.write("Use: "+Prop1.PropertyUse+"<br>");

</script>

</body>

</html>
***** End of Code *****

Sincerely,

Gene Wirchenko
 
E

Evertjan.

Gene Wirchenko wrote on 11 nov 2011 in comp.lang.javascript:
The following code is meant is extend an object definition. The
code works. My question is whether it works best. Is the way that I
have initialised the properties in Commercial that are from RealEstate
the best way to do it? I have a feeling

Perhaps I do not understand the Canadian "best way",
but I strongly oppose these words in programming.

Programming is not only a science but also an art, and it should be.

Therefore there cann't be a "best" way to do it, as valueing art is
subjective.

Asking for a subjective "better" way to do something seems okay to me,
as some ways seem quite silly to someone having found, by craft or by
search, a "subjectively better" way.

This NG is an ideal place to discuss the logic behind the
is subjective "better way".

Sometimes [or often?] even a weak or strong consensus may be formed, see
the FAQ, but such consesnus does not mean "best".
 
B

beegee

Dear JavaScripters:
< [snip] >

If you are trying to accomplish inheritance - not entirely clear from
the names of your objects and relevant code - please see

http://javascript.crockford.com/prototypal.html

In fact, please read all of Crockford, all of the FAQ and some other
book on javascript and then repost. Thanks,

Bob

Or hell, just use $.extend() and go to the jQuery group. Yeah, I went
there.
 
E

Elegie

On 11/11/2011 05:02, Gene Wirchenko wrote :

Hi,
1) How should I be doing it?

Using your example, what you probably are looking for is:

---
function RealEstate(PropertyLocation, PropertyValue) {
this.PropertyLocation=PropertyLocation;
this.PropertyValue=PropertyValue;
}

function Commercial (PropertyZoning, PropertyUse) {
this.PropertyZoning=PropertyZoning;
this.PropertyUse=PropertyUse;
}

Commercial.prototype=new RealEstate("Kamloops",150000);

var Prop1=new Commercial("C-1","light commercial");
---

Javascript inheritance is said to be "prototype-based". You create an
object, which is called a prototype, then you bind it to a constructor.
When the constructor is invoked (i.e. when the constructor function is
called using the "new" operator), then a new object is constructed, and
this object holds an implicit link towards the prototype. Later, when
resolving properties on this object, javascript first looks up
properties directly declared on the object, and if it finds nothing,
goes up the prototype chain until it finds something fitting (or
eventually fails when the chain has been consumed).

You appear to start walking on the path of javascript inheritance. I
therefore suggest that, before you go on, grab a copy of the
specification (I use the Third Edition and refer below to related
sections of this Edition, but you may try the Fifth Edition), and read
section 10 "Execution Contexts".

The specification can be found here:

<URL:http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm>

When you have read that section, try and study Douglas Crockford's
articles which have been pointed out by other posters.
2) In the template statement, what does the new do? I have seen
code with it and without it. Both seem to work, but which way is
correct/better?

Both are correct, but they should be used in different contexts.
Basically, using the "new" operator invokes the function as a
constructor and not as a function (i.e. it creates an object, sets its
prototype, and binds the "this" value used in the function's body to
that object).

See ECMAScript 262 Third Edition, section 13 "Function Definition".

Regards,
Elegie.
 
D

Denis McMahon

function RealEstate(PropertyLocation, PropertyValue) {
this.PropertyLocation=PropertyLocation;
this.PropertyValue=PropertyValue;
}

function Commercial (PropertyZoning, PropertyUse) {
this.PropertyZoning=PropertyZoning;
this.PropertyUse=PropertyUse;
}

Commercial.prototype=new RealEstate("Kamloops",150000);

var Prop1=new Commercial("C-1","light commercial"); ---

Wouldn't that mean that all Commercial properties have the same location
and value?

I think the OP wants to be able to assign different locations and values
to different commercial properties.

eg: http://www.sined.co.uk/tmp/objects.htm

I'm sure that someone will be along soon to tell us that I've done it
wrong, although he won't actually go so far as to post "the right way",
because he much prefers to criticise the coding of others than to expose
his own code to critical comment.

Rgds

Denis McMahon
 
J

John G Harris

Dear JavaScripters:

< [snip] >

If you are trying to accomplish inheritance - not entirely clear from
the names of your objects and relevant code - please see

http://javascript.crockford.com/prototypal.html
<snip>

Or you could do inheritance the javascript way.

Which is?

(Remember me? I am the OP. I did have a question.)

One way to do it is shown in my web page at :

<http://www.jgharris.demon.co.uk/jsfeats/JSfeats.html#seca1p1>

There are obviously several minor variations possible. For instance, you
can make use of the 'call' function in constructors if you don't need to
go too far back in time.


John
 
J

John G Harris

On 11/11/2011 05:02, Gene Wirchenko wrote :

Hi,


Using your example, what you probably are looking for is:

---
function RealEstate(PropertyLocation, PropertyValue) {
this.PropertyLocation=PropertyLocation;
this.PropertyValue=PropertyValue;
}

function Commercial (PropertyZoning, PropertyUse) {
this.PropertyZoning=PropertyZoning;
this.PropertyUse=PropertyUse;
}

Commercial.prototype=new RealEstate("Kamloops",150000);

var Prop1=new Commercial("C-1","light commercial");
---
<snip>

Your Commercial prototype is not a good idea. How, for instance, would a
new Commercial object get a property location that isn't Kamloops?

John
 
B

beegee

  <snip>

Or you could do inheritance the javascript way.

How is this not the javascript way?

To me it looks exactly like the example you provided except you do not
create a new intermediate object when you inherit.


Bob
 
J

John G Harris

I think the OP wants to be able to assign different locations and values
to different commercial properties.

eg: http://www.sined.co.uk/tmp/objects.htm

I'm sure that someone will be along soon to tell us that I've done it
wrong, although he won't actually go so far as to post "the right way",
because he much prefers to criticise the coding of others than to expose
his own code to critical comment.

Speak of the devil and up he pops. Thank you for your kind comments.

First off : there is no "the right way". There are many ways and several
of them are equally clean; the rest have various amounts of messiness
built in, and some are downright perverse.

In your example you build a Commercial object by doing :

var factory = new Commercial();
factory.setLocation("13 West Street");
factory.setValue("750000");
factory.setZoning("Light Industry");
factory.setUse("Vehicle Bodyshop");

My view is that it's simpler and easier to read to do

var factory = new Commercial
( "13 West Street",
"750000",
"Light Industry",
"Vehicle Bodyshop" );

If you have many Commercial objects to create you have to remember to
type four factory.setX(...) every time. Forget one line once and
you've got a bug and a lot of code to look through to find it.

John
 
T

Thomas 'PointedEars' Lahn

Denis said:
Wouldn't that mean that all Commercial properties have the same location
and value?

I think the OP wants to be able to assign different locations and values
to different commercial properties.

eg: http://www.sined.co.uk/tmp/objects.htm

I'm sure that someone will be along soon to tell us that I've done it
wrong,

You have done it wrong.
although he won't actually go so far as to post "the right way",

The right way is to _not_ have Commercial instances inherit from the same
(empty Property) instance as both of your codes did. So you have certainly
not avoided the mistake that you mention above; instead, you have added
other mistakes on top of it. One, because there are no methods to refer to
them, the variable declarations in `Property' are mystical incantations; the
code will "work" exactly the same without them.

The intention of the original code obviously was to have Commercial
instances inherit from RealEstate.prototype, i. e. Commercial was intended
to be a specialization of RealEstate. In your nonsense code, Commercial
ends up to be a specialization of Property, and RealEstate is missing.
because he much prefers to criticise the coding of others than to expose
his own code to critical comment.

[I am sure someone has told you before that you are an obnoxious ignorant
who does not have a first idea about these programming languages or the APIs
they can be used with (see also your one dysfunctional, and the other
unnecessarily inefficiant and incompatible checkbox toggle suggestions
earlier).]

The first thing to make this work without changing too much of the original
code is get the identifiers right. Property names should be concise, and
start lowercase:

function RealEstate(location, value)
{
this.location = location;
this.value = value;
}

function Commercial(zoning, use)
{
this.zoning = zoning;
this.use = use;
}

Then one needs to set up the prototype chain properly, i. e. let Commercial
inherit from RealEstate.prototype, not from a single RealEstate instance.
This is facilitated with a method that Lasse Reichstein Nielsen introduced
here years ago as clone() [1], that I named inheritFrom() afterwards (as it
does not really clone) [2], and that Douglas Crockford eventually came to
name object() (at least in his interesting, but slightly erroneous
JavaScript introduction at Yahoo! [3]). In its non-optimized form (see
jsx.object.inheritFrom() for the optimization [4]), it is:

function inheritFrom(proto)
{
function Dummy() {}
Dummy.prototype = proto;
return new Dummy();
}

Commercial.prototype = inheritFrom(RealEstate.prototype);

With this approach, a Dummy instance is defined as the prototype of
Commercial instances that does nothing else than to inherit from
RealEstate.prototype, thus establishing the prototype chain link between
Commercial instances and RealEstate.prototype:

(new Commercial()) → (Commercial.prototype === new Dummy())
→ RealEstate.prototype

But as Commercial.prototype.constructor is now Dummy implicitly, it would be
well that that be fixed (this part you got right):

Commercial.prototype.constructor = Commercial;

Afterwards the Dummy instance that Commercial.prototype refers to can be
refined, serving as the prototype of Commercial instances.

(Function.prototype.extend() does all that in JSX:eek:bject.js [4]. It allows
this inheritance approach to be written

Commercial.extend(RealEstate, extensions);

as you would in natural language. That also adds a `_super' property to
Commercial.prototype to refer to RealEstate.prototype, and it adds a
`_super' property to Commercial to refer to RealEstate, among other things.)

The latter which then can be created with

var prop1 = new Commercial("C-1", "light commercial");


PointedEars
______
[1]
<https://groups.google.com/forum/#!msg/comp.lang.javascript/CT4_IGmUob8/Gi4CKqG7WYoJ>
or <2004-05-20
[3]
<https://groups.google.com/forum/#!topic/comp.lang.javascript/HMJosLXN9LQ>
or <2007-11-30
[2]
<http://pointedears.de/websvn/filedetails.php?repname=JSX&path=/trunk/object.js>
[3] <
>; 2007
 
E

Elegie

On 12/11/2011 17:52, John G Harris wrote :

Hello John,
Your Commercial prototype is not a good idea. How, for instance, would a
new Commercial object get a property location that isn't Kamloops?

Actually I did not think about it at all, I simply wanted to introduce
the OP to the concept of prototype chain, and have him reflect about it
a bit...

Regards,
Elegie.
 
J

John G Harris

How is this not the javascript way?

To me it looks exactly like the example you provided except you do not
create a new intermediate object when you inherit.

I think you've misunderstood Crockford's way. There is no extra
intermediate object, but there are extra steps.

Doing it his way, first you call the following function, supplying your
desired prototype object, and hence prototype chain, as the parameter
'o' :

function object(o)
{
function F() {}
F.prototype = o;
return new F();
}

(The function might have a different name, or be a method of some
non-global object, depending on your preferences).

This gives you a new object with the right inheritance, but no
properties of its own. Now you have to add the desired own properties,
so :

var obj = object(protoCommercial);

obj.PropertyLocation = "Kamloops";
obj.PropertyValue = 150000;
obj.PropertyZoning = "C-1";
obj.PropertyUse = "light commercial";

This gives you a new Commercial object.

Incidentally, you make protoCommercial the same way from protoRealEstate
except you'll mostly be attaching methods rather than data properties.

Obviously, if you are going to make more than one Commercial object
you'll package all this code in a function. What are you going to call
it? You shouldn't call it Commercial else other people will think it's
a constructor. To follow the Java naming convention like so many do you
have to call it something like newCommercial .

So, to make a new Commercial object you end up doing

var c = newCommercial("Kamloops", 150000, "C-1", "light commercial");

Now what have you achieved? You've done exactly what a constructor would
have done but with two extra function calls. Was it worth it?


John
 
D

Denis McMahon

Speak of the devil and up he pops. Thank you for your kind comments.

I wasn't actually talking about you. But if you recognise yourself in the
description ;)
In your example ....
My view is that it's simpler and easier to read to do

var factory = new Commercial
( "13 West Street",
"750000",
"Light Industry",
"Vehicle Bodyshop" );

So you'd prefer http://www.sined.co.uk/tmp/objects2.htm then.

(I thought I posted this or something like it yesterday, but it hasn't
appeared in my newsfeed yet)

Rgds

Denis McMahon
 
B

beegee

I think you've misunderstood Crockford's way. There is no extra
intermediate object, but there are extra steps.

Crockford's way:

function object(o)
{
1) function F() {}
F.prototype = o;
2) return new F();
}

Your way (and mine sometimes):

1) Commercial.prototype=new RealEstate("Kamloops",150000);


There, I counted em for you. function F() {} is the intermediate
object and the reason you want to do this is exactly so that the new
object does *not* inherit pre-existing property values.

Now in this case, the OP wants to inherit existing property values and
perhaps create a number of child objects. I'm really ambivalent about
the value of classical OO in Javascript. I've used it effectively
exactly once and if I had to do it over, would probably go a different
route. Once you start down this road, you start missing the other
aspects of class inheritance like super constructors and destructors,
function overloading, interfaces and protected,private members. Each
of these paradigms has to be emulated in JS and to what purpose?

Far better, in my opinion, to focus on data/ui separation and
performance.

bob
 
G

Gene Wirchenko

On 12/11/2011 17:52, John G Harris wrote :

Hello John,


Actually I did not think about it at all, I simply wanted to introduce
the OP to the concept of prototype chain, and have him reflect about it
a bit...

I already have been doing so. That is why I wrote my test code
in the first place.

Sincerely,

Gene Wirchenko
 
E

Elegie

On 14/11/2011 05:21, Gene Wirchenko wrote :

Hi,
I already have been doing so. That is why I wrote my test code
in the first place.

Reading you code in the first place induced me to think that while you
were aware about inheritance (a way to structurally link objects
together, so as to share properties and methods), you did not know
anything about prototyped inheritance.

In short:
- you did not use any "prototype", but rather referred to some property
named "template", about which I know nothing (my knowledge may be at
fault though, because I only know the Third Edition of ECMAScript),
- you (apparently) tried to relate together two objects which shared
common property identifiers, which could obviously only result in some
properties shadowing the others,
- you did not know what the "new" keyword would do, i.e. the difference
between the [[call]] and the [[construct]] behaviors of a function.

Consequently, I decided to give you an example that would let you
discover the concept of prototype chain, and in addition I pointed you
out to relevant parts of the specification, which could help you get a
more solid knowledge about it.

The way that I participate in this group has many facets (as can be
ascertained by reading my previous posts on this group):
- with beginners - and I put you in that category, as you have yourself
qualified as such - I always do "tutoring javascript", i.e. point out to
specifications and give working examples, but simplified to the point
that the OP can understand it, and build on them to advance further on
the javascript path,
- with proficient posters, I provide scripts solving problems, but not
optimized (i.e. weak API, straightforward design), because I believe
that context matters and that the OP has the skills to adjust the script
to his / her needs,
- with experts, I usually do not provide scripts (because they would
write them as easily as I do), but discuss aspects of the problem,
giving my intuitions and reasonings. I do that very rarely though,
because there are few "expert" topics which are of interest to me.

So, to sum it up, the example I provided was intentionally simple, since
it was a product of "tutoring javascript". The problem that John and
Denis have mentioned was probably the natural next step in understanding
the prototype chain, and it is not a complicated one to solve, provided
you really understand how the prototype chain works. The end-result,
however, is not satisfying from a pattern point of view, and should lead
you to ponder thoughtfully what should and should not be done with
javascript inheritance (and what other alternate patterns you could use
to better structure your code).

I am sorry that you do not appreciate my contributions. I will therefore
put you at ease and refrain from posting them in your topics, so that
you can concentrate on more useful answers. I wish you to enjoy your
stay in that newsgroup, and to soon become proficient with the technology.

Regards,
Elegie.
 
J

John G Harris

Crockford's way:

function object(o)
{
1) function F() {}
F.prototype = o;
2) return new F();
}

Your way (and mine sometimes):

1) Commercial.prototype=new RealEstate("Kamloops",150000);

No, no, no, no, no, and yet again no!

A Commercial.prototype object and a RealEstate object have different
jobs to do. The Commercial.prototype object's job is to hold only
methods, except in peculiar circumstances. A RealEstate object's job is
to hold only data, except in rare circumstances. To repeat : they are
different kinds of object holding different kinds of properties.

There, I counted em for you. function F() {} is the intermediate
object and the reason you want to do this is exactly so that the new
object does *not* inherit pre-existing property values.

a) There are two functions - object and F - and so two function objects.
Both are created at program start up. I don't see how either can be
called intermediate, but if one can then both are.

b) The whole point of inheritance is to inherit. You only want to avoid
inheriting if you've supplied the wrong prototype object. And the use of
the object function doesn't stop you picking up unwanted values from the
wrong kind of prototype object.

Now in this case, the OP wants to inherit existing property values and
perhaps create a number of child objects.

You don't mean "existing property values", do you? Inherited property
names, perhaps?

What on earth is a child object?

I'm really ambivalent about
the value of classical OO in Javascript. I've used it effectively
exactly once and if I had to do it over, would probably go a different
route. Once you start down this road, you start missing the other
aspects of class inheritance like
super constructors and

The Commercial constructor knows that its 'super constructor' is called
RealEstate, and doesn't want to call it as a constructor by the way.

destructors,

Java doesn't have destructors, and some diehard Java enthusiasts insist
they aren't needed in spite of being given examples of dangling
resources.

ECMAScript assumes that garbage collection is sufficient, as does Java.

function overloading,

Overloading assumes that different functions can have the same name
provided the parameters have different types.

ECMAScript parameters aren't typed, so you must use different function
names instead. (Or a type-detection mess in one catch-all function).

interfaces
Why?


and protected,private members.

Private properties are useful in million line programs. They stop
programmers deliberately corrupting the design.

It's not compulsory to corrupt the design.

Each
of these paradigms has to be emulated in JS and to what purpose?

You only emulate the features you need : the purpose being that a
particular feature is needed in your application.

Far better, in my opinion, to focus on data/ui separation and
performance.

Calling extra functions can't be good for performance.

Far better to focus on making your code maintainable in two years time
when the customer wants changes.


John
 

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

Staff online

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top