Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"x.constructor == Foo" vs "x instanceof Foo"

320 views
Skip to first unread message

kj

unread,
Jan 27, 2008, 4:47:54 PM1/27/08
to


My book (Flanagan's JavaScript: The Definitive Guide, 5th ed.)
implies on page 111 that the following two constructs are equivalent:

( x.constructor == Foo )

and

( x instanceof Foo )

The author states that the instanceof operator computes its result
by examining the value of its first argument's the constructor
property.

However, I've recently ran into a situation that contradicts this.

I've been trying to understand jQuery better, with the aid of
Firefox's Firebug debugger. At one breakpoint, there's one variable
(I'll call it x) for which

x instanceof jQuery

is true, but

x.constructor == jQuery

is false.

In fact, x.constructor is Object, but (Object instanceof jQuery)
is false.

Could anyone explain to me what's going on?

TIA!

Kynn



--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.

liam...@gmail.com

unread,
Jan 27, 2008, 5:12:37 PM1/27/08
to

I know that there are difference in the way that instanceof is
determined vs. x.constructor. In this instance it sounds like it's an
issue with the way that JQuery handles it's extends functionality. Not
having used JQuery a great deal, could you shed some light on the way
that JQuery extends?

kj

unread,
Jan 27, 2008, 6:15:28 PM1/27/08
to

>I know that there are difference in the way that instanceof is
>determined vs. x.constructor. In this instance it sounds like it's an
>issue with the way that JQuery handles it's extends functionality. Not
>having used JQuery a great deal, could you shed some light on the way
>that JQuery extends?

That went over my head! :-) But I'll do my best...

The jQuery object does have an extend method, if that's what you're
asking. It can be invoked in a few ways, but probably the most
general one is something like

jQuery.extend( bool, target, obj1, obj2, obj3 ... );

If bool is false, extend copies values from obj1, obj2, obj3, etc.
into the corresponding slots in target. If bool is true, instead
of copying it extends the slots when the the contents of both the
target and source slots are themselves are objects. (That's a very
broad-strokes description!)

But I find your question also puzzling, because it suggests that
"extends" is a function that, when available, gets called automatically
by the interpreter in certain situations, just like, e.g., valueOf
or toString. If this is the case then I'm even more mystified than
before, because I've never heard of such a thing. (FWIW, Flanagan
doesn't even *mention* extend.)

Kynn

P.S. I really need to get myself an authoritative reference on
JavaScript... I thought that Flanagan's book was it, but just
today I've run into a few topics (such as the const keyword) that
Flanagan doesn't even *mention*. I'm wondering if "extend" will
be another such blind spot...

Joost Diepenmaat

unread,
Jan 27, 2008, 6:16:30 PM1/27/08
to
kj <so...@987jk.com.invalid> writes:

> My book (Flanagan's JavaScript: The Definitive Guide, 5th ed.)
> implies on page 111 that the following two constructs are equivalent:
>
> ( x.constructor == Foo )
>
> and
>
> ( x instanceof Foo )

They're not. For one thing, obj.constructor does the wrong thing when
the constructor has a prototype assigned to it, since the constructor is
actually determined by the prototype.

function Super() {}
function Sub() {}
Sub.prototype = new Super(); // note: this is wrong, but since it
// but everybody does it and it works.
// more or less.
// unless you actually want to read the
// the constructor later

var sub = new Sub(); // like here, sub.constructor == Super!

alert(sub.constructor == Sub); // false
alert(sub.constructor == Super); // true
alert(sub instanceof Sub); // true
alert(sub instanceof Super); // true

also, instanceof checks the full prototype chain, while obj.constructor
can only be a single value, so it's useless for inherited objects.

> The author states that the instanceof operator computes its result
> by examining the value of its first argument's the constructor
> property.
>
> However, I've recently ran into a situation that contradicts this.

As shown above, you're right. One of the problems is that you can't
access an object's prototype directly, you apparently have to use
obj.constructor.prototype, *but* obj.constructor is read from the
objects's prototype, which is why replacing a constructor's prototype
outright leads to issues. My current strategy in those cases where I
need access to the constructor directly is to merge properties into the
existing prototype instead.

Joost.

kj

unread,
Jan 27, 2008, 6:32:37 PM1/27/08
to

>kj <so...@987jk.com.invalid> writes:


Thank you very much! Your post (and liamgegan's) finally clarified
the matter for me. Indeed, in the jQuery source, I see that
jQuery.prototype gets assigned an anonymous object...

kynn

liam...@gmail.com

unread,
Jan 27, 2008, 6:59:09 PM1/27/08
to
On Jan 28, 10:15 am, kj <so...@987jk.com.invalid> wrote:

Sorry, I didn't mean to confuse :D

Extends functionality is unavailable in Javascript, but is a
fundamental feature of other OOP languages (including AS 2+ [also
ECMA]). In Javascript as in AS1, Extends functionality needed to be
simulated in one of 3 ways, each with advantages of their own (but
also with many and varied problems):
a) copy all methods from subclass into superclass and provided an
implemented constructor. I always hated this way as it's more
implementation than an extension.
b) sub.__proto__ = super.prototype; This seems to be the most correct
type to me, but can easily break down expected behaviour in the sub/
super relationship if you don't understand it properley;
c) sub.prototype = new Super(); Probably the most used method, but the
class instanciation always seemed superfluous to me.

Thomas 'PointedEars' Lahn

unread,
Jan 27, 2008, 7:39:57 PM1/27/08
to
Joost Diepenmaat wrote:
> kj <so...@987jk.com.invalid> writes:
>> My book (Flanagan's JavaScript: The Definitive Guide, 5th ed.)
>> implies on page 111 that the following two constructs are equivalent:
>>
>> ( x.constructor == Foo )
>>
>> and
>>
>> ( x instanceof Foo )
>
> They're not.

True. I wonder how long it will take until everybody recognizes that
Flanagan actually has no clue what he is writing about.

> For one thing, obj.constructor does the wrong thing when the constructor
> has a prototype assigned to it, since the constructor is actually determined
> by the prototype.

The constructor is the Function object that was used to create the object.
It has a `prototype' property implicitly. It is not that this property is
assigned a value that makes the `constructor' property of the created object
useless, but when this value is not an object that provides a user-defined
`constructor' property to refer to the constructor.

> function Super() {}
> function Sub() {}
> Sub.prototype = new Super(); // note: this is wrong, but since it
> // but everybody does it and it works.

Not everybody does it, as it does not work, because it is wrong. This
statement does not add Super.prototype to the prototype chain of Sub
objects; it adds a newly created Super object there:

new Sub() --> Sub.prototype --> new Super() --> Super.prototype --> ...
--> Object.prototype

So there is no real prototype-based inheritance anymore as any property
value that is defined for Super objects only in their constructor is
inherited from that object through the prototype chain, even though
Super.prototype does not need to have that property or provides a different
default value for it.

One way to do it properly is this oft-recommended approach:

function extend(P)
{
function Dummy() {}
Dummy.prototype = P;
return new Dummy();
}

Sub.prototype = extend(Super.prototype);

The resulting prototype chain is then

new Sub() --> Sub.prototype === new Dummy() --> Dummy.prototype ===
Super.prototype --> ... --> Object.prototype

as it should be. (A prototype object is inserted into the prototype chain.)

> // more or less.

It fails whenever prototype properties are involved, for example. Search
the newsgroup for details.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>

Joost Diepenmaat

unread,
Jan 28, 2008, 6:54:39 AM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Joost Diepenmaat wrote:
>> kj <so...@987jk.com.invalid> writes:
>>> My book (Flanagan's JavaScript: The Definitive Guide, 5th ed.)
>>> implies on page 111 that the following two constructs are equivalent:
>>>
>>> ( x.constructor == Foo )
>>>
>>> and
>>>
>>> ( x instanceof Foo )
>>
>> They're not.
>
> True. I wonder how long it will take until everybody recognizes that
> Flanagan actually has no clue what he is writing about.

For some reason /nobody/ I've read gets OO javascript right except
Crockford. And I just looked up that page in Flanagan, and he *does*
just outright say instanceof checks the constructor property. He should
know better.

>> For one thing, obj.constructor does the wrong thing when the constructor
>> has a prototype assigned to it, since the constructor is actually determined
>> by the prototype.
>
> The constructor is the Function object that was used to create the object.
> It has a `prototype' property implicitly. It is not that this property is
> assigned a value that makes the `constructor' property of the created object
> useless, but when this value is not an object that provides a user-defined
> `constructor' property to refer to the constructor.

Yes, you're right about that. I could have stated that more clearly.

>> function Super() {}
>> function Sub() {}
>> Sub.prototype = new Super(); // note: this is wrong, but since it
>> // but everybody does it and it works.
>
> Not everybody does it, as it does not work, because it is wrong.This
> statement does not add Super.prototype to the prototype chain of Sub
> objects;

Of course it does. Just confusingly. See your diagram directly below.

> it adds a newly created Super object there:
>
> new Sub() --> Sub.prototype --> new Super() --> Super.prototype --> ...
> --> Object.prototype

For example:

function Super() {}
Super.prototype.thingy=42;

function Sub() {}
Sub.prototype = new Super();

alert((new Sub()).thingy); // 42.

> So there is no real prototype-based inheritance anymore as any property
> value that is defined for Super objects only in their constructor is
> inherited from that object through the prototype chain, even though
> Super.prototype does not need to have that property or provides a different
> default value for it.

So? Super() does not add any properties, and even if it did, that won't
make it wrong. It's just that constructors confuse matters.

> One way to do it properly is this oft-recommended approach:
>
> function extend(P)
> {
> function Dummy() {}
> Dummy.prototype = P;
> return new Dummy();
> }
>
> Sub.prototype = extend(Super.prototype);
>
> The resulting prototype chain is then
>
> new Sub() --> Sub.prototype === new Dummy() --> Dummy.prototype ===
> Super.prototype --> ... --> Object.prototype

What? Just. No. That's just even *more* confusing. Why not do this if
you want real prototyping:

var SubProto = {};
var SuperProto = extend(SubProto);
var super = extend(sub);

and just forget about "new constructor()" altogether and use extend() to
create *all* objects. Constructors are an ugly, ugly hack in JavaScript
anyway.

--
Joost.

Joost Diepenmaat

unread,
Jan 28, 2008, 7:01:09 AM1/28/08
to
Joost Diepenmaat <jo...@zeekat.nl> writes:

> What? Just. No. That's just even *more* confusing. Why not do this if
> you want real prototyping:
>
> var SubProto = {};
> var SuperProto = extend(SubProto);
> var super = extend(sub);

I meant:

var SubProto = {};
var SuperProto = extend(SubProto);

var super = extend(SuperProto);

Sorry about the confusion.

Joost.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 1:16:09 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Joost Diepenmaat wrote:
>>> kj <so...@987jk.com.invalid> writes:
>>>> My book (Flanagan's JavaScript: The Definitive Guide, 5th ed.)
>>>> implies on page 111 that the following two constructs are equivalent:
>>>>
>>>> ( x.constructor == Foo )
>>>>
>>>> and
>>>>
>>>> ( x instanceof Foo )
>>> They're not.
>> True. I wonder how long it will take until everybody recognizes that
>> Flanagan actually has no clue what he is writing about.
>
> For some reason /nobody/ I've read gets OO javascript right except
> Crockford. [...]

Including you? ;-)

>>> function Super() {}
>>> function Sub() {}
>>> Sub.prototype = new Super(); // note: this is wrong, but since it
>>> // but everybody does it and it works.
>> Not everybody does it, as it does not work, because it is wrong.This
>> statement does not add Super.prototype to the prototype chain of Sub
>> objects;
>
> Of course it does. Just confusingly. See your diagram directly below.

OK, it does add Super.prototype, but it does not add it in the proper way.

>> it adds a newly created Super object there:
>>
>> new Sub() --> Sub.prototype --> new Super() --> Super.prototype --> ...
>> --> Object.prototype
>
> For example:
>
> function Super() {}
> Super.prototype.thingy=42;
>
> function Sub() {}
> Sub.prototype = new Super();
>
> alert((new Sub()).thingy); // 42.

You miss the point. For example:

function Super() {}
Super.prototype.items = [];

function Sub() {}
Sub.prototype = new Super();

var sub1 = new Sub();
var sub2 = new Sub();
sub1.items.push(42);

// yields [42], instead of [] as it should
sub2.items

Lasse Reichstein Nielsen already pointed that out when this issue first (or
at least most intensively) came up here. You really should increase the
range of your research.

>> So there is no real prototype-based inheritance anymore as any property
>> value that is defined for Super objects only in their constructor is
>> inherited from that object through the prototype chain, even though
>> Super.prototype does not need to have that property or provides a different
>> default value for it.
>
> So? Super() does not add any properties, and even if it did, that won't
> make it wrong.

Yes, it would. The object inherited from would not be Super.prototype, but
a Super object (no pun intended):

function Super()
{
this.foo = "bar";
}

function Sub() {}
Sub.prototype = new Super();

var sub1 = new Sub();
Super.prototype.foo = 42;

// yields "bar", instead of 42 as it should
sub1.foo

> It's just that constructors confuse matters.

I don't agree.

>> One way to do it properly is this oft-recommended approach:
>>
>> function extend(P)
>> {
>> function Dummy() {}
>> Dummy.prototype = P;
>> return new Dummy();
>> }
>>
>> Sub.prototype = extend(Super.prototype);
>>
>> The resulting prototype chain is then
>>
>> new Sub() --> Sub.prototype === new Dummy() --> Dummy.prototype ===
>> Super.prototype --> ... --> Object.prototype
>
> What? Just. No. That's just even *more* confusing.

No, it is has been proven a correct approach, if not *the* correct one.
Again, you should search the newsgroup.

[imported correction from <8763xep...@zeekat.nl>]


> Why not do this if you want real prototyping:
>
> var SubProto = {};
> var SuperProto = extend(SubProto);

> var super = extend(SuperProto);

Nonsense. User-defined objects should inherit from prototype (Object)
objects, not from constructor (Function) objects.

It is possible to pass the constructor instead of the prototype object, but
extend() can be renamed clone() and the necessary hard-coding of the
prototype property in it would prevent this code reuse. Besides, passing
the prototype object explicitly shows the caller what is going to happen;
I consider that a Good Thing.

> and just forget about "new constructor()" altogether and use extend() to
> create *all* objects. Constructors are an ugly, ugly hack in JavaScript
> anyway.

I don't think so.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 1:31:44 PM1/28/08
to
Thomas 'PointedEars' Lahn wrote:
> [imported correction from <8763xep...@zeekat.nl>]
>> Why not do this if you want real prototyping:
>>
>> var SubProto = {};
>> var SuperProto = extend(SubProto);
>> var super = extend(SuperProto);

`super' is a reserved word.

> Nonsense. User-defined objects should inherit from prototype (Object)
> objects, not from constructor (Function) objects.

> [...]

Please ignore that, I was overlooking that you are using Object objects already.

>> and just forget about "new constructor()" altogether and use extend() to

>> create *all* objects. [...]

While the identifiers are confusing and even misleading, it certainly is an
interesting idea: One Object object would inherit from the other, indeed.
However, it looks as if there was a bug in it and I just don't see it yet.


PointedEars

Dr J R Stockton

unread,
Jan 28, 2008, 1:30:28 PM1/28/08
to
In comp.lang.javascript message <fnj3ag$jk0$1...@reader2.panix.com>, Sun,
27 Jan 2008 23:15:28, kj <so...@987jk.com.invalid> posted:

>
>P.S. I really need to get myself an authoritative reference on
>JavaScript...

So get ISO/IEC 16262, free as a PDF.

> I thought that Flanagan's book was it, but just
>today I've run into a few topics (such as the const keyword) that
>Flanagan doesn't even *mention*. I'm wondering if "extend" will
>be another such blind spot...

Remember that a script engine author needs to know everything in the
current and the imminent standards, and should also know what other
script engines actually do. For that, ordinary books cannot be expected
to suffice.

But a page author needs to know only those standards with which current
and recent script engines are compliant, and what the common browsers
actually do; if he knows anything else, he must keep the two sets of
knowledge quite separate in his mind.

--
(c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
<URL:http://www.merlyn.demon.co.uk/clpb-faq.txt> RAH Prins : c.l.p.b mFAQ;
<URL:ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip> Timo Salmi's Turbo Pascal FAQ.

Joost Diepenmaat

unread,
Jan 28, 2008, 3:05:15 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> You miss the point. For example:
>
> function Super() {}
> Super.prototype.items = [];
>
> function Sub() {}
> Sub.prototype = new Super();
>
> var sub1 = new Sub();
> var sub2 = new Sub();
> sub1.items.push(42);
>
> // yields [42], instead of [] as it should
> sub2.items

That's expected. Prototypes aren't templates, they're objects in their
own right, and sharing a prototype, which is exactly what constructors
do to their generated objects, means you're sharing the prototype's
properties until you override them by setting them in the super object.
But you know that.

>> It's just that constructors confuse matters.
>
> I don't agree.

I belief they do: constructors are just way of setting prototypes and
properties but they look way too much like classes / class-based
constructors.

Joost.


Joost Diepenmaat

unread,
Jan 28, 2008, 3:09:18 PM1/28/08
to
Joost Diepenmaat <jo...@zeekat.nl> writes:

> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>
>> You miss the point. For example:
>>
>> function Super() {}
>> Super.prototype.items = [];
>>
>> function Sub() {}
>> Sub.prototype = new Super();
>>
>> var sub1 = new Sub();
>> var sub2 = new Sub();
>> sub1.items.push(42);
>>
>> // yields [42], instead of [] as it should
>> sub2.items
>
> That's expected. Prototypes aren't templates, they're objects in their
> own right, and sharing a prototype, which is exactly what constructors
> do to their generated objects, means you're sharing the prototype's
> properties until you override them by setting them in the super

> object. ^^^^^

I meant: sub object

Joost.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 3:44:32 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> You miss the point. For example:
>>
>> function Super() {}
>> Super.prototype.items = [];
>>
>> function Sub() {}
>> Sub.prototype = new Super();
>>
>> var sub1 = new Sub();
>> var sub2 = new Sub();
>> sub1.items.push(42);
>>
>> // yields [42], instead of [] as it should
>> sub2.items
>
> That's expected.

No, it is _not_ expected at all that two objects derived from the same
prototype share their property *values*. The very point about objects
is that they have identity, that they *differ* from each other.

> Prototypes aren't templates, they're objects in their own right,

I'm afraid you are in error here. Prototypes are objects in their
own right, but the term "prototype", translatable at least into all
Indo-European languages, including Nederlands if I may say so, has
the meaning of "template". In engineering, a working prototype is
the first thing you need to make a series of machines with similar
functionality and properties. Note that since the words are not
being used in the OOP sense here, the connection is most obvious.

See also http://en.wikipedia.org/wiki/Prototype pp.


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

RobG

unread,
Jan 28, 2008, 4:03:15 PM1/28/08
to
On Jan 28, 10:39 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
[...]

> One way to do it properly is this oft-recommended approach:
>
>   function extend(P)
>   {
>     function Dummy() {}
>     Dummy.prototype = P;
>     return new Dummy();
>   }

Richard Cornford suggested that can be written more efficiently by
reusing the Dummy constructor:

var extend = (function(){
function Dummy(){}
return (function(P){


Dummy.prototype = P;
return new Dummy();

});
})();

<URL:
http://groups.google.com.au/group/comp.lang.javascript/browse_frm/thread/fc74c84dfefe26a0/21965e62bfb3aa9f?hl=en&lnk=gst&q=clone+object#21965e62bfb3aa9f
>


--
Rob

Joost Diepenmaat

unread,
Jan 28, 2008, 4:11:34 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Joost Diepenmaat wrote:
>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>> You miss the point. For example:
>>>
>>> function Super() {}
>>> Super.prototype.items = [];
>>>
>>> function Sub() {}
>>> Sub.prototype = new Super();
>>>
>>> var sub1 = new Sub();
>>> var sub2 = new Sub();
>>> sub1.items.push(42);
>>>
>>> // yields [42], instead of [] as it should
>>> sub2.items
>>
>> That's expected.
>
> No, it is _not_ expected at all that two objects derived from the same
> prototype share their property *values*. The very point about objects
> is that they have identity, that they *differ* from each other.

Javascript does not clone from a prototype, it just links the new object
to its prototype and does property lookup via the prototype chain. If
you want cloning of certain properties (and you usually don't want to
clone ALL properties) you have to make it happen yourself.

Provided you know that, nothing about the above code should be
confusing. Well except that it becomes very unclear why you'd need
constructors at all.

>> Prototypes aren't templates, they're objects in their own right,
>
> I'm afraid you are in error here. Prototypes are objects in their
> own right, but the term "prototype", translatable at least into all
> Indo-European languages, including Nederlands if I may say so, has
> the meaning of "template". In engineering, a working prototype is
> the first thing you need to make a series of machines with similar
> functionality and properties. Note that since the words are not
> being used in the OOP sense here, the connection is most obvious.

I thought this was a JavaScript group. The meaning of the word in
JavaScript is what matters to me.

Joost.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 4:27:31 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Joost Diepenmaat wrote:
>>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>>> You miss the point. For example:
>>>>
>>>> function Super() {}
>>>> Super.prototype.items = [];
>>>>
>>>> function Sub() {}
>>>> Sub.prototype = new Super();
>>>>
>>>> var sub1 = new Sub();
>>>> var sub2 = new Sub();
>>>> sub1.items.push(42);
>>>>
>>>> // yields [42], instead of [] as it should
>>>> sub2.items
>>> That's expected.
>> No, it is _not_ expected at all that two objects derived from the same
>> prototype share their property *values*. The very point about objects
>> is that they have identity, that they *differ* from each other.
>
> Javascript does not clone from a prototype, it just links the new object
> to its prototype and does property lookup via the prototype chain. If
> you want cloning of certain properties (and you usually don't want to
> clone ALL properties) you have to make it happen yourself.

You are not making sense. Don't you see that your *wrong* assignment can
make objects share not only their properties, but also their property
values, i.e. clones them?

> Provided you know that, nothing about the above code should be
> confusing. Well except that it becomes very unclear why you'd need
> constructors at all.

Disagreed.

>>> Prototypes aren't templates, they're objects in their own right,
>> I'm afraid you are in error here. Prototypes are objects in their
>> own right, but the term "prototype", translatable at least into all
>> Indo-European languages, including Nederlands if I may say so, has
>> the meaning of "template". In engineering, a working prototype is
>> the first thing you need to make a series of machines with similar
>> functionality and properties. Note that since the words are not
>> being used in the OOP sense here, the connection is most obvious.
>
> I thought this was a JavaScript group. The meaning of the word in
> JavaScript is what matters to me.

The meaning of the word in software engineering, including programming in
ECMAScript implementations, is clearly derived from the meaning of the word
in general engineering. It is simply unreasonable to deny that.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 4:36:30 PM1/28/08
to
RobG wrote:

> [...] Thomas 'PointedEars' Lahn [...] wrote:
>> One way to do it properly is this oft-recommended approach:
>>
>> function extend(P)
>> {
>> function Dummy() {}
>> Dummy.prototype = P;
>> return new Dummy();
>> }
>
> Richard Cornford suggested that can be written more efficiently by
> reusing the Dummy constructor:
>
> var extend = (function(){
> function Dummy(){}
> return (function(P){
> Dummy.prototype = P;
> return new Dummy();
> });
> })();
>
> <URL:
> http://groups.google.com.au/group/comp.lang.javascript/browse_frm/thread/fc74c84dfefe26a0/21965e62bfb3aa9f?hl=en&lnk=gst&q=clone+object#21965e62bfb3aa9f

Thanks, I was looking for that. However, you should consider that the
increased runtime efficiency gained by declaring the Dummy() constructor
only once is mitigated by the reduced memory efficiency caused by the
continued allocation of memory due to the closure. And since there are
more issues with closures than without them, I would avoid them here.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

Joost Diepenmaat

unread,
Jan 28, 2008, 4:40:38 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

>> Javascript does not clone from a prototype, it just links the new object
>> to its prototype and does property lookup via the prototype chain. If
>> you want cloning of certain properties (and you usually don't want to
>> clone ALL properties) you have to make it happen yourself.
>
> You are not making sense. Don't you see that your *wrong* assignment can
> make objects share not only their properties, but also their property
> values, i.e. clones them?

Linking to a prototype does not clone anything. That's the reason the
properties are shared. If they were cloned they wouldn't be shared.

>> Provided you know that, nothing about the above code should be
>> confusing. Well except that it becomes very unclear why you'd need
>> constructors at all.
>
> Disagreed.

*shrug*

>> I thought this was a JavaScript group. The meaning of the word in
>> JavaScript is what matters to me.
>
> The meaning of the word in software engineering, including programming in
> ECMAScript implementations, is clearly derived from the meaning of the word
> in general engineering. It is simply unreasonable to deny that.

I didn't deny that. Stick to the subject.

Joost.

Joost Diepenmaat

unread,
Jan 28, 2008, 4:43:39 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Thanks, I was looking for that. However, you should consider that the
> increased runtime efficiency gained by declaring the Dummy() constructor
> only once is mitigated by the reduced memory efficiency caused by the
> continued allocation of memory due to the closure. And since there are
> more issues with closures than without them, I would avoid them here.

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

No closure. Though I would be amazed if it would have any significant
impact on memory use.

Joost.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 4:53:09 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Thanks, I was looking for that. However, you should consider that the
>> increased runtime efficiency gained by declaring the Dummy() constructor
>> only once is mitigated by the reduced memory efficiency caused by the
>> continued allocation of memory due to the closure. And since there are
>> more issues with closures than without them, I would avoid them here.
>
> function Dummy(){}
^^^^^
> function extend(proto) {
> Dummy.prototype=proto;
^^^^^
> return new Dummy();
> }
>
> No closure. [...]

I think there is one. `Dummy' was declared in the definition
context of `extend' that `extend' reproduces when it is called;
that is how a closure is defined.


PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm>

Joost Diepenmaat

unread,
Jan 28, 2008, 4:58:40 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Joost Diepenmaat wrote:
>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>> Thanks, I was looking for that. However, you should consider that the
>>> increased runtime efficiency gained by declaring the Dummy() constructor
>>> only once is mitigated by the reduced memory efficiency caused by the
>>> continued allocation of memory due to the closure. And since there are
>>> more issues with closures than without them, I would avoid them here.
>>
>> function Dummy(){}
> ^^^^^
>> function extend(proto) {
>> Dummy.prototype=proto;
> ^^^^^
>> return new Dummy();
>> }
>>
>> No closure. [...]
>
> I think there is one. `Dummy' was declared in the definition
> context of `extend' that `extend' reproduces when it is called;
> that is how a closure is defined.

If you're defining closures like that, every function that calls another
function, or accesses any other global property would be a closure:

function a() { alert() }
function b() { a(); }

My informal definition is that a closure is a function that keeps
references to objects that are defined in an outer lexical scope. Dummy
here is just a property of the global object, not a lexical variable.

Joost.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 5:32:10 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>> Javascript does not clone from a prototype, it just links the new object
>>> to its prototype and does property lookup via the prototype chain. If
>>> you want cloning of certain properties (and you usually don't want to
>>> clone ALL properties) you have to make it happen yourself.
>> You are not making sense. Don't you see that your *wrong* assignment can
>> make objects share not only their properties, but also their property
>> values, i.e. clones them?
>
> Linking to a prototype does not clone anything. That's the reason the
> properties are shared. If they were cloned they wouldn't be shared.

That would define how you define "clone". Suffice it to say that two
objects implicitly share their property values this way when derived from
the same prototype object is definitely counter-intuitive. It is the direct
result of the wrong application of prototype-based inheritance in ECMAScript
implementations.

>>> I thought this was a JavaScript group. The meaning of the word in
>>> JavaScript is what matters to me.
>> The meaning of the word in software engineering, including programming in
>> ECMAScript implementations, is clearly derived from the meaning of the word
>> in general engineering. It is simply unreasonable to deny that.
>
> I didn't deny that. Stick to the subject.

You must be kidding.


EOD

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 5:43:33 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Joost Diepenmaat wrote:
>>> function Dummy(){}
>> ^^^^^
>>> function extend(proto) {
>>> Dummy.prototype=proto;
>> ^^^^^
>>> return new Dummy();
>>> }
>>>
>>> No closure. [...]
>> I think there is one. `Dummy' was declared in the definition
>> context of `extend' that `extend' reproduces when it is called;
>> that is how a closure is defined.
>
> If you're defining closures like that,

It is not my definition.

> every function that calls another function,

Not every function. It depends on where the other function was defined.

> or accesses any other global property would be a closure:

> [...]

That is correct. Probably that is why Flanagan made his oversimplifying
false statement.

> My informal definition is that a closure is a function that keeps
> references to objects that are defined in an outer lexical scope. Dummy
> here is just a property of the global object, not a lexical variable.

Note that functions are first-class objects in ECMAScript implementations.

Joost Diepenmaat

unread,
Jan 28, 2008, 5:49:38 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Joost Diepenmaat wrote:
>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>>> Javascript does not clone from a prototype, it just links the new object
>>>> to its prototype and does property lookup via the prototype chain. If
>>>> you want cloning of certain properties (and you usually don't want to
>>>> clone ALL properties) you have to make it happen yourself.
>>> You are not making sense. Don't you see that your *wrong* assignment can
>>> make objects share not only their properties, but also their property
>>> values, i.e. clones them?
>>
>> Linking to a prototype does not clone anything. That's the reason the
>> properties are shared. If they were cloned they wouldn't be shared.
>
> That would define how you define "clone". Suffice it to say that two
> objects implicitly share their property values this way when derived from
> the same prototype object is definitely counter-intuitive. It is the direct
> result of the wrong application of prototype-based inheritance in ECMAScript
> implementations.

AFAIK the current implementations behaviour is exactly according to the
spec. Section 4.3.5 of Ecma 262.

You may not like the spec, but the way properties are resolved in
JavaScript is not unique. There are other prototype-based systems that
work exactly the same (except they usually don't use constructors like
that, they just let you set & read the prototype directly).

It's an extremely simple system and it keeps memory use down and
run-time modification extremely simple, but it generally makes propery
lookup slower.

>>>> I thought this was a JavaScript group. The meaning of the word in
>>>> JavaScript is what matters to me.
>>> The meaning of the word in software engineering, including programming in
>>> ECMAScript implementations, is clearly derived from the meaning of the word
>>> in general engineering. It is simply unreasonable to deny that.
>>
>> I didn't deny that. Stick to the subject.
>
> You must be kidding.

Read it again.

Joost.

Joost Diepenmaat

unread,
Jan 28, 2008, 5:57:41 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Joost Diepenmaat wrote:
>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>> Joost Diepenmaat wrote:
>>>> function Dummy(){}
>>> ^^^^^
>>>> function extend(proto) {
>>>> Dummy.prototype=proto;
>>> ^^^^^
>>>> return new Dummy();
>>>> }
>>>>
>>>> No closure. [...]
>>> I think there is one. `Dummy' was declared in the definition
>>> context of `extend' that `extend' reproduces when it is called;
>>> that is how a closure is defined.
>>
>> If you're defining closures like that,
>
> It is not my definition.

Then you won't mind me demonstrating that it's wrong:

function a() { alert("First") }

function b() { a() };

function a() { alert("Second") }

b();

>> every function that calls another function,
>
> Not every function. It depends on where the other function was defined.

See code above. We're accessing a global property, not a lexical
variable. The fact that the variable is a function doesn't matter.

>> or accesses any other global property would be a closure:
>> [...]
>
> That is correct. Probably that is why Flanagan made his oversimplifying
> false statement.

Which statement?

Joost.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 6:12:46 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Joost Diepenmaat wrote:
>>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>>>> Javascript does not clone from a prototype, it just links the new object
>>>>> to its prototype and does property lookup via the prototype chain. If
>>>>> you want cloning of certain properties (and you usually don't want to
>>>>> clone ALL properties) you have to make it happen yourself.
>>>> You are not making sense. Don't you see that your *wrong* assignment can
>>>> make objects share not only their properties, but also their property
>>>> values, i.e. clones them?
>>> Linking to a prototype does not clone anything. That's the reason the
>>> properties are shared. If they were cloned they wouldn't be shared.
>> That would define how you define "clone". Suffice it to say that two
>> objects implicitly share their property values this way when derived from
>> the same prototype object is definitely counter-intuitive. It is the direct
>> result of the wrong application of prototype-based inheritance in ECMAScript
>> implementations.
>
> AFAIK the current implementations behaviour is exactly according to the
> spec. Section 4.3.5 of Ecma 262.
>
> You may not like the spec, [...]

JFTR: Quite the contrary. The above was _not_ to say that the
implementation was wrong, but the application of the implementation
*by you*.

>>>>> I thought this was a JavaScript group. The meaning of the word in
>>>>> JavaScript is what matters to me.
>>>> The meaning of the word in software engineering, including programming in
>>>> ECMAScript implementations, is clearly derived from the meaning of the word
>>>> in general engineering. It is simply unreasonable to deny that.
>>> I didn't deny that. Stick to the subject.
>> You must be kidding.
>
> Read it again.

BTDT. Your reply to my explanation is still ridiculous.


PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

Joost Diepenmaat

unread,
Jan 28, 2008, 6:30:04 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:
> JFTR: Quite the contrary. The above was _not_ to say that the
> implementation was wrong, but the application of the implementation
> *by you*.

Sharing a prototype's properties is not wrong by itself. It's what
prototypes in javascript are there for. The only time it's wrong is when
you actually don't want to share the properties, just copies. And
javascript does not provide any /built in/ mechanism to do that, so I
really don't see what you're complaining about.

Joost.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 6:31:30 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Joost Diepenmaat wrote:
>>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>>> Joost Diepenmaat wrote:
>>>>> function Dummy(){}
>>>> ^^^^^
>>>>> function extend(proto) {
>>>>> Dummy.prototype=proto;
>>>> ^^^^^
>>>>> return new Dummy();
>>>>> }
>>>>>
>>>>> No closure. [...]
>>>> I think there is one. `Dummy' was declared in the definition
>>>> context of `extend' that `extend' reproduces when it is called;
>>>> that is how a closure is defined.
>>> If you're defining closures like that,
>> It is not my definition.
>
> Then you won't mind me demonstrating that it's wrong:

The definition certainly is not wrong; maybe my interpretation of it in this
context is.

> function a() { alert("First") }
>
> function b() { a() };
>
> function a() { alert("Second") }
>
> b();

The second declaration for `a' overwrites the reference with one to another
Function object before b() is executed. ISTM you have just proved that
there is a closure :)

>>> every function that calls another function,
>> Not every function. It depends on where the other function was defined.
>
> See code above. We're accessing a global property, not a lexical
> variable. The fact that the variable is a function doesn't matter.

That seems contradictory.

>>> or accesses any other global property would be a closure:
>>> [...]
>> That is correct. Probably that is why Flanagan made his oversimplifying
>> false statement.
>
> Which statement?

That one cited in
<bc992427-bf06-4308...@1g2000hsl.googlegroups.com>

Different thread, same source of confusion. Sigh. [psf 10.1]

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 6:41:03 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> JFTR: Quite the contrary. The above was _not_ to say that the
>> implementation was wrong, but the application of the implementation *by
>> you*.
>
> Sharing a prototype's properties is not wrong by itself. [...] The only

> time it's wrong is when you actually don't want to share the properties,
> just copies. And javascript does not provide any /built in/ mechanism to
> do that, so I really don't see what you're complaining about.

Please review my example more thoroughly.

I was not talking about properties, but about non-default property *values*.
Sharing *them* is certainly not what prototypes are designed for. Usually,
you would not want to automatically have something appended to list #2 if
you appended it to list #1, and vice-versa, just because both targets are
lists (here: arrays). It might merely be an interesting hack to take
advantage of the unconventional application of prototype-based inheritance,
to say the least.

Joost Diepenmaat

unread,
Jan 28, 2008, 6:45:42 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

>> function a() { alert("First") }
>>
>> function b() { a() };
>>
>> function a() { alert("Second") }
>>
>> b();
>
> The second declaration for `a' overwrites the reference with one to another
> Function object before b() is executed. ISTM you have just proved that
> there is a closure :)

I expected that reply and have prepared the following, demonstrating
that the lookup of a() in b() is done via dynamic, not lexical scoping.

function a() { alert("first") }

function b() { a() }

c = { a: function() { alert("second") } };
a();

with (c) {
a();
}

>>>> every function that calls another function,
>>> Not every function. It depends on where the other function was defined.
>>
>> See code above. We're accessing a global property, not a lexical
>> variable. The fact that the variable is a function doesn't matter.
>
> That seems contradictory.

Javascript variables that aren't declared (with var) in a function scope
or as a function argument are dynamic, defaulting to the global object's
property via whatever with() scopes are in place.

The same goes for functions: named functions defined in the global scope
are set as dynamic variables. Named functions defined within a with(X)
in the global scope are put in X. Named functions defined within a
function scope are lexical. I'm not sure what with() within a function
does.

Compare the above with:

function a() {
alert("first");
}

function b() { a() }

function c() {
function a() {
alert("second");
};
b();
}

a();
c();


>>>> or accesses any other global property would be a closure:
>>>> [...]
>>> That is correct. Probably that is why Flanagan made his oversimplifying
>>> false statement.
>>
>> Which statement?
>
> That one cited in
> <bc992427-bf06-4308...@1g2000hsl.googlegroups.com>
>
> Different thread, same source of confusion. Sigh. [psf 10.1]

I don't see the connection.

Joost.

Joost Diepenmaat

unread,
Jan 28, 2008, 6:54:15 PM1/28/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> I was not talking about properties, but about non-default property *values*.
> Sharing *them* is certainly not what prototypes are designed for. Usually,
> you would not want to automatically have something appended to list #2 if
> you appended it to list #1, and vice-versa, just because both targets are
> lists (here: arrays). It might merely be an interesting hack to take
> advantage of the unconventional application of prototype-based inheritance,
> to say the least.

I noticed that, and I can see where that usage may be confusing. But
all prototype *values* are shared by design.

Properties are just references to objects. Modifying the object does not
change the shared status. Direct assigment to a "prototyped" property
creates a new reference in the "subclassed" object that points to a new
value object, overriding but not changing the prototyped property.

Can we at least agree that when you know what you're doing this sort of
thing can be useful, and not automatically wrong?

Joost.

Joost Diepenmaat

unread,
Jan 28, 2008, 7:06:54 PM1/28/08
to
Joost Diepenmaat <jo...@zeekat.nl> writes:

> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>
>>> function a() { alert("First") }
>>>
>>> function b() { a() };
>>>
>>> function a() { alert("Second") }
>>>
>>> b();
>>
>> The second declaration for `a' overwrites the reference with one to another
>> Function object before b() is executed. ISTM you have just proved that
>> there is a closure :)
>
> I expected that reply and have prepared the following, demonstrating
> that the lookup of a() in b() is done via dynamic, not lexical scoping.
>
> function a() { alert("first") }
>
> function b() { a() }
>
> c = { a: function() { alert("second") } };
> a();
>
> with (c) {
> a();
> }

Never mind that. It's wrong and my analysis was wrong.

Joost.

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 8:52:23 PM1/28/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> I was not talking about properties, but about non-default property
>> *values*. Sharing *them* is certainly not what prototypes are designed
>> for. Usually, you would not want to automatically have something
>> appended to list #2 if you appended it to list #1, and vice-versa, just
>> because both targets are lists (here: arrays). It might merely be an
>> interesting hack to take advantage of the unconventional application of
>> prototype-based inheritance, to say the least.
>
> I noticed that, and I can see where that usage may be confusing. But all
> prototype *values* are shared by design.

Quite the contrary. That is exactly what I wanted to point out: properties
are shared by design, but not property values. Meaning that if you modify
the property value of an object that is *not* a prototype object, it is
*not* by design that all other objects that have the same prototype object
in their prototype chain have their property value changed accordingly.

> Properties are just references to objects.

They can store references to objects, they don't have to. In my example
(that is probably only Lasse's slightly adapted) they do (`items' stores a
reference to a shared Array object), which is the cause of the
counter-intuitive result.

> Modifying the object does not change the shared status. Direct assigment
> to a "prototyped" property creates a new reference in the "subclassed"
> object that points to a new value object, overriding but not changing the
> prototyped property.
>
> Can we at least agree that when you know what you're doing this sort of
> thing can be useful, and not automatically wrong?

We can. I don't deny that there can be useful applications of it, but I
doubt that they are commonplace.

RobG

unread,
Jan 28, 2008, 9:34:47 PM1/28/08
to
On Jan 29, 7:43 am, Joost Diepenmaat <jo...@zeekat.nl> wrote:

> Thomas 'PointedEars' Lahn <PointedE...@web.de> writes:
>
> > Thanks, I was looking for that. However, you should consider that the
> > increased runtime efficiency gained by declaring the Dummy() constructor
> > only once is mitigated by the reduced memory efficiency caused by the
> > continued allocation of memory due to the closure.

That only becomes an issue if it causes paging to disc or some
secondary storage. I have no idea how much memory is consumed by an
empty function, I'll guess that it's very small in comparison to the
kind of non-trivial script that might use it.

> > And since there are
> > more issues with closures than without them, I would avoid them here.

The only issue I can think of with closures is related to IE memory
leaks, I don't think that's an issue here. There might be other
concerns with inappropriate use, but the usage here is quite specific
and should not cause any problems.

>
> function Dummy(){}
> function extend(proto) {
> Dummy.prototype=proto;
> return new Dummy();
>
> }
>
> No closure. Though I would be amazed if it would have any significant
> impact on memory use.

There are always pros and cons... the above makes Dummy a global
variable that can be re-assigned by any function that wants to. In
Richard's original (and Crockford's), the use of a closure keeps it
private. If there is a need to dynamically modify or replace it
(which seems contrary to the whole point of the extend method, but
let's consider it) then a privileged function can be provided to do
that.

The amount of memory consumed in either case is trivial, I think the
performance gain (again, it's very small in one-of cases) outweighs
the memory consumed.


--
Rob

Thomas 'PointedEars' Lahn

unread,
Jan 28, 2008, 10:08:54 PM1/28/08
to
RobG wrote:
> The amount of memory consumed in either case is trivial, I think the
> performance gain (again, it's very small in one-of cases) outweighs
> the memory consumed.

I don't know what you mean by "one-of cases", but my benchmarks show that
the performance gain is negligible, too. With 10'000 iterations, it's a gain of

30 ms in Firefox 2.0.0.11,
125 ms in IE 7, and
16 ms in Opera 9.24.

All running on Windows XP SP 2 on a Pentium M 740, 1.73 GHz, 1 GB RAM, 1.2
GB Swap (at the time of testing).

Benchmark source code:

function extend(P)
{
function Dummy() {}
Dummy.prototype = P;
return new Dummy();
}

var extend2 = (function()
{
function Dummy() {}
return function(P)
{


Dummy.prototype = P;
return new Dummy();

};
})();

if (typeof console == "undefined")
{
console = {log: function(s) { window.alert(s); }};
}

function Super() {}
function Sub() {}

var start = new Date();
for (var i = 10000; i--;)
Sub.prototype = extend(Super.prototype);
console.log(new Date() - start);

start = new Date();
for (i = 10000; i--;)
Sub.prototype = extend2(Super.prototype);
console.log(new Date() - start);

VK

unread,
Jan 29, 2008, 1:51:15 AM1/29/08
to
On Jan 28, 12:47 am, kj <so...@987jk.com.invalid> wrote:
> My book (Flanagan's JavaScript: The Definitive Guide, 5th ed.)
> implies on page 111 that the following two constructs are equivalent:
>
> ( x.constructor == Foo )
>
> and
>
> ( x instanceof Foo )
>
> The author states that the instanceof operator computes its result
> by examining the value of its first argument's the constructor
> property.
>
> However, I've recently ran into a situation that contradicts this.
>
> I've been trying to understand jQuery better, with the aid of
> Firefox's Firebug debugger. At one breakpoint, there's one variable
> (I'll call it x) for which
>
> x instanceof jQuery
>
> is true, but
>
> x.constructor == jQuery
>
> is false.
>
> In fact, x.constructor is Object, but (Object instanceof jQuery)
> is false.
>
> Could anyone explain to me what's going on?

http://blogs.msdn.com/ericlippert/archive/2003/11/06/53352.aspx has it
all explained in details.

kj

unread,
Jan 29, 2008, 8:32:15 AM1/29/08
to
In <479D245D...@PointedEars.de> Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> I wonder how long it will take until everybody recognizes that
> Flanagan actually has no clue what he is writing about.

Well, clearly I'm one of those who was pretty slow at figuring this
out... (Though, irrespective of matters of accuracy, I've never
been not fond of Flanagan's ponderous tome.)

But if not Flanagan's book, then what?

Is there a better alternative for someone looking for an authoritative
JavaScript reference book? I suppose I could use the ECMA specs...
But is there something closer to JavaScript (whatever that is)?

I should say that I dislike most computer language "bibles" that
one can buy. It is clear that most of them aim for *bulk* rather
than substance. (It wouldn't surprise me if some of them used
thicker paper than normal, to create an imposing "authoritative"
presence in bookstores' shelves!)

So, to be more specific, my gold-standard for language reference
books is Harbison and Steele's "C: a reference manual". It's as
authoritative as any formal C specification, but significantly more
readable, without any superfluous handholding fluff... (The also
excellent Python Reference Manual by van Rossum is a very close
second.)

Is there something like that for JavaScript?

kynn
--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.

RobG

unread,
Jan 29, 2008, 8:44:06 AM1/29/08
to
On Jan 29, 1:08 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> RobG wrote:
> > The amount of memory consumed in either case is trivial, I think the
> > performance gain (again, it's very small in one-of cases) outweighs
> > the memory consumed.
>
> I don't know what you mean by "one-of cases"

Single cases where extend() is called once or only a few times.


>, but my benchmarks show that
> the performance gain is negligible, too.  With 10'000 iterations, it's a gain of
>
>  30 ms in Firefox 2.0.0.11,

[...]

Yes, it's more a feel-good measure than a must-have. But if extend()
is to be used as a library function, why not optimise it? Anyhow,
it's up to individuals to chose how it's implemented, I just thought
it worth while posting an alternative.


--
Rob

John G Harris

unread,
Jan 30, 2008, 4:03:00 PM1/30/08
to
On Mon, 28 Jan 2008 at 21:44:32, in comp.lang.javascript, Thomas
'PointedEars' Lahn wrote:
>Joost Diepenmaat wrote:

<snip>
>> That's expected.
>
>No, it is _not_ expected at all that two objects derived from the same
>prototype share their property *values*.

Objects don't 'derive' from the same prototype object, they share it.


>The very point about objects
>is that they have identity, that they *differ* from each other.

In C++ and Java two objects can share the same class-static data; they
only differ in the non-static data. Javascript has something similar; it
allows data to be shared as long as it isn't written to, and allows
functions to be shared for calling.


>> Prototypes aren't templates, they're objects in their own right,
>
>I'm afraid you are in error here. Prototypes are objects in their
>own right, but the term "prototype", translatable at least into all
>Indo-European languages, including Nederlands if I may say so, has
>the meaning of "template". In engineering, a working prototype is
>the first thing you need to make a series of machines with similar
>functionality and properties. Note that since the words are not
>being used in the OOP sense here, the connection is most obvious.

<snip>

Perhaps you've never visited one of the prototype Concordes. They aren't
'templates'; they're real aeroplanes that flew. (Very fast).

More to the point, the ECMAScript standard defines it's use of the word
'prototype' (Section 4.3.5, for instance). That's what it means in the
standard whatever you might like and whatever an external dictionary or
encyclopaedia says.

You'll be unhappy to hear that the C standard defines 'prototype' to
mean a piece of text like
int f(int a, int b);

John
--
John Harris

ron.h...@gmail.com

unread,
Feb 2, 2008, 12:35:27 AM2/2/08
to
On Jan 28, 1:03 pm, RobG <rg...@iinet.net.au> wrote:

> [...]

> Richard Cornford suggested that can be written more efficiently by
> reusing the Dummy constructor:
>

> var extend = (function(){
>     function Dummy(){}
>     return (function(P){


>         Dummy.prototype = P;
>         return new Dummy();

>     });
>
> })();
>

That could depend on how efficient one finds closures versus function
creation to be. Nonetheless, an "extend" function can be invoked
without use of closures or function creation. E.g.,

Object.prototype.
extend = function ( f )
{
if ( f !== null ) {
var
o = new arguments.callee( ( arguments.callee.prototype = this )
&& null )
;
return ( f && f.apply( o, [].slice.call( arguments, 1 ) ) ), o;
}
}
;

Moreover, ofen functionality trumps efficiency. Ignoring issues
related to Object.prototype, the above includes additional facility of
an extended object tailoring function and parameters, optionally
provided. In this form there is an intuitive inversion of the
Javascript paradigm, where the object being extended now has
precedence over the "new object" tailoring function.

../rh

Joost Diepenmaat

unread,
Feb 11, 2008, 2:34:13 PM2/11/08
to
kj <so...@987jk.com.invalid> writes:

> My book (Flanagan's JavaScript: The Definitive Guide, 5th ed.)
> implies on page 111 that the following two constructs are equivalent:
>
> ( x.constructor == Foo )
>
> and
>
> ( x instanceof Foo )
>
> The author states that the instanceof operator computes its result
> by examining the value of its first argument's the constructor
> property.
>
> However, I've recently ran into a situation that contradicts this.

I had some free time this weekend to do a somewhat extensive write-up
about this problem. It may be of interested to some people.

http://joost.zeekat.nl/constructors-considered-mildly-confusing.html

Feel free to ask questions or comment if it seems wrong or
incomprehensible.

--
Joost Diepenmaat | blog: http://joost.zeekat.nl/ | work: http://zeekat.nl/

Lasse Reichstein Nielsen

unread,
Feb 13, 2008, 12:50:14 PM2/13/08
to
Joost Diepenmaat <jo...@zeekat.nl> writes:

Comments:

Re. Footnote.
"For most intents, javascript does not have classes. 1]" and
"1] There are system-defined classes: Function ..."
Not true. For all intents, Javascript does not have classes.
The examples you give are constructor functions (except Math, which
is just an object, and Class, which is not in, at least, EcmaScript 3ed.)
As built-on functions they can do some tricks that user defined functions
can't, but they are not classes.

Apart from that, it well described.
I particularly like the drawings. It makes so much sense to see:

var foo = new Foo();

as giving the object graph:

(foo) (Foo)
\ /
[[prototype]] prototype
\ /
(Foo.prototype)
|
[[Prototype]]
|
(Object.prototype)

/L
--
Lasse Reichstein Nielsen - l...@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'

Joost Diepenmaat

unread,
Feb 13, 2008, 2:12:46 PM2/13/08
to
Lasse Reichstein Nielsen <l...@hotpop.com> writes:

> Comments:
>
> Re. Footnote.
> "For most intents, javascript does not have classes. 1]" and
> "1] There are system-defined classes: Function ..."
> Not true. For all intents, Javascript does not have classes.
> The examples you give are constructor functions (except Math, which
> is just an object, and Class, which is not in, at least, EcmaScript 3ed.)
> As built-on functions they can do some tricks that user defined functions
> can't, but they are not classes.

Not quite: "Note that these classes are *not* the same as the pre-defined
objects (constructors) with the same name, and cannot be directly
accessed in any way."

The "classes" here are the values of the internal [[Class]] property,
which, according to the spec, is used to do type-checking and probably
optimization.

And the Math object does really have a [[Class]] property of "Math". See
ecmas-262 section 15.8.

> Apart from that, it well described.

Thanks :-)

Thomas 'PointedEars' Lahn

unread,
Feb 13, 2008, 2:49:21 PM2/13/08
to
Joost Diepenmaat wrote:
> Lasse Reichstein Nielsen <l...@hotpop.com> writes:
>> Comments:
>>
>> Re. Footnote.
>> "For most intents, javascript does not have classes. 1]" and
>> "1] There are system-defined classes: Function ..."
>> Not true. For all intents, Javascript does not have classes.
>> The examples you give are constructor functions (except Math, which
>> is just an object, and Class, which is not in, at least, EcmaScript 3ed.)
>> As built-on functions they can do some tricks that user defined functions
>> can't, but they are not classes.
>
> Not quite: "Note that these classes are *not* the same as the pre-defined
> objects (constructors) with the same name, and cannot be directly
> accessed in any way."
>
> The "classes" here are the values of the internal [[Class]] property,
> which, according to the spec, is used to do type-checking and probably
> optimization.
>
> And the Math object does really have a [[Class]] property of "Math". See
> ecmas-262 section 15.8.

Please understand that the existence of an [[Class]] property that is purely
a specification mechanism (see ES3 Final, section 8.6.2) does not make
implementations of ECMAScript Ed. 3 programming languages with classes as in
class-based inheritance.

Joost Diepenmaat

unread,
Feb 13, 2008, 2:55:03 PM2/13/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Please understand that the existence of an [[Class]] property that is purely
> a specification mechanism (see ES3 Final, section 8.6.2) does not make
> implementations of ECMAScript Ed. 3 programming languages with classes as in
> class-based inheritance.

I do understand that. I'll update the text a bit to make this clearer.

Lasse Reichstein Nielsen

unread,
Feb 13, 2008, 3:07:02 PM2/13/08
to
Joost Diepenmaat <jo...@zeekat.nl> writes:

> Not quite: "Note that these classes are *not* the same as the pre-defined
> objects (constructors) with the same name, and cannot be directly
> accessed in any way."

What?!? I need to read the entire paragraph before commenting?
Preposterous! *spittle*

Ahem, anyway, indeed the specification uses the word "Class", but in a
sense that could equally well have been called "Type". I would ignore
it, as even mentioning will confuse people more familiar with the use
of "class" in class based object orientation.

I have seen people expecting CSS "class"'es to be inheritable (then
again, CSS have both "class" and "inherit", so it's a double whammy
on the confuzion front :)

Joost Diepenmaat

unread,
Feb 13, 2008, 3:11:22 PM2/13/08
to
Lasse Reichstein Nielsen <l...@hotpop.com> writes:
> Ahem, anyway, indeed the specification uses the word "Class", but in a
> sense that could equally well have been called "Type". I would ignore
> it, as even mentioning will confuse people more familiar with the use
> of "class" in class based object orientation.

I'm not even sure "Type" is the right word for what it's supposed to
do. Something like "tag" might be more descriptive, since it's nothing
more than a string value.

> I have seen people expecting CSS "class"'es to be inheritable (then
> again, CSS have both "class" and "inherit", so it's a double whammy
> on the confuzion front :)

Well, sucks to be them :)

Anyway I changed the footnote to:

"There are system-defined classes, or at least in the specs there are
several values for the internal [[Class]] property: Function, Object,
Array, RegExp, Boolean, Number, Math, Date, Error and String. These are
*not* required to exist at all, are (almost) invisible to the user, and
nothing is defined about their behaviour, except that the specs are
explained using them. Actual implementations can do as they please as
long as the result from the javascript programmer's point of view is
the same (this applies to all internal properties, including
[[Prototype]])."

"A user cannot add a new class, though the host system may define
more. A user-defined constructor that doesn't explicitly return
something else always returns an object of "class" Object."

Which should scare everybody enough while still being technically
correct :-)

Thomas 'PointedEars' Lahn

unread,
Feb 13, 2008, 3:44:48 PM2/13/08
to

You should remove the entire footnote as it is pure nonsense.


PointedEars

Joost Diepenmaat

unread,
Feb 13, 2008, 4:07:23 PM2/13/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> You should remove the entire footnote as it is pure nonsense.

You don't expect me to do anything based on that, do you? There is a
point to the foot note. I don't really care if you don't like it. If you
have any reasoned suggestions to improve it, (or even if you have good
reasons to delete it) I'd be more than happy to consider them.

Thomas 'PointedEars' Lahn

unread,
Feb 13, 2008, 5:21:21 PM2/13/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> You should remove the entire footnote as it is pure nonsense.
>
> You don't expect me to do anything based on that, do you? There is a
> point to the foot note. I don't really care if you don't like it. If you
> have any reasoned suggestions to improve it, (or even if you have good
> reasons to delete it) I'd be more than happy to consider them.

I won't even begin with denying every point that you wrote and provide
a valid reason for it. The reasons are at least in the specification.

Joost Diepenmaat

unread,
Feb 13, 2008, 5:29:29 PM2/13/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> I won't even begin with denying every point that you wrote and provide
> a valid reason for it. The reasons are at least in the specification.

As far as I can see the note is correct with regards to the spec. I'm
fine with you not providing a correction.

Dr J R Stockton

unread,
Feb 13, 2008, 3:18:30 PM2/13/08
to
In comp.lang.javascript message <ve4s69...@hotpop.com>, Wed, 13 Feb
2008 18:50:14, Lasse Reichstein Nielsen <l...@hotpop.com> posted:

>Lasse Reichstein Nielsen - l...@hotpop.com

^^^^^^^^^^^^^^ Kaput.

--
(c) John Stockton, nr London, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links;
Astro stuff via astron-1.htm, gravity0.htm ; quotings.htm, pascal.htm, etc.
No Encoding. Quotes before replies. Snip well. Write clearly. Don't Mail News.

questorJs

unread,
Feb 14, 2008, 9:26:10 AM2/14/08
to
Interesting discussions, I must say. Prototypical inheritance is quite
confusing in JavaScript. Personally I find that it helps a lot to
simply erase from memory certain concepts when I am working with
JavaScript. These being "class", "type" and even "template", that is,
anything that has to do with classical inheritance. Then, all that is
left is objects. To me, that is the key to understand JavaScript.
Everything is an object (except for the primitives, that actually
function as objects). We know that user defined objects can be created
inline (literal notation) and by defining constructor functions and
associating certain properties to them.

Prototypical inheritance basically means that an object inherits from
another object. It doesn't inherit from another function. This means
that the *wrong* behaviour demonstrated in a previous post with arrays
is actually the *correct* behaviour. This is due to the fact that
everything happens runtime and because we are working all the time
with objects. Functions in JavaScript are, after all, nothing but
objects with certain properties and functionality. Functions are a
special kind of an object that can be invoked with the () operator.

There is no *right* way to do stuff in JavaScript and there is no
*wrong* way either. It't just that there are many ways to create
objects: With prototypical shared inheritance, prototypical unshared
inheritance, mixins, closures, constructors, object factories etc. The
key is to use the right method when appropriate. Sometimes memory is
an issue, other times it is not.

/Helgi

RobG

unread,
Feb 14, 2008, 3:52:46 PM2/14/08
to
On Feb 15, 12:26 am, questorJs <helgi.kristjans...@gmail.com> wrote:
> Interesting discussions, I must say. Prototypical inheritance is quite
> confusing in JavaScript.

I don't think it's more confusing, just different. Most programmers
come to javascript from another language and probably already know
classical inheritance. They often assume javascript works the same
way.

Those who learn only javascript tend not to know about prototypes for
some time, you can do an awful lot without knowing anything about them
or using inheritance.


> Personally I find that it helps a lot to
> simply erase from memory certain concepts when I am working with
> JavaScript. These being "class", "type" and even "template", that is,
> anything that has to do with classical inheritance. Then, all that is
> left is objects. To me, that is the key to understand JavaScript.
> Everything is an object (except for the primitives, that actually
> function as objects).

I tend to think of primitives as objects that act like primitives for
convenience.


--
Rob

Joost Diepenmaat

unread,
Feb 14, 2008, 7:19:43 PM2/14/08
to
RobG <rg...@iinet.net.au> writes:

> On Feb 15, 12:26 am, questorJs <helgi.kristjans...@gmail.com> wrote:
>> Interesting discussions, I must say. Prototypical inheritance is quite
>> confusing in JavaScript.
>
> I don't think it's more confusing, just different. Most programmers
> come to javascript from another language and probably already know
> classical inheritance. They often assume javascript works the same
> way.

IMO what's actually confusing about prototypes in javascript is that the
language tries to hide the prototypes behind constructor functions,
which when taken at face value (i.e. when you're making assumptions
based on the semantics of well known class-oriented systems) break at
the point where you start using "class" inheritance, and *then* you have
to re-think the way you're building objects. And then constructors
become more and more useless. At least, that's what happened to me.

The strange thing is that a prototype system like javascript has is in
principle much easier to comprehend (and implement) than systems where
classes are special.

Thomas 'PointedEars' Lahn

unread,
Feb 14, 2008, 7:41:29 PM2/14/08
to
Joost Diepenmaat wrote:
> IMO what's actually confusing about prototypes in javascript is that the
> language tries to hide the prototypes behind constructor functions,
> which when taken at face value (i.e. when you're making assumptions
> based on the semantics of well known class-oriented systems) break at
> the point where you start using "class" inheritance, and *then* you have
> to re-think the way you're building objects. And then constructors
> become more and more useless. At least, that's what happened to me.

Just because you don't know what you are doing, much less what you are
talking about, you are not automatically making a valid point against
prototype-based inheritance as it is provided by ECMAScript implementations.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>

Joost Diepenmaat

unread,
Feb 14, 2008, 7:46:03 PM2/14/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Just because you don't know what you are doing, much less what you are
> talking about, you are not automatically making a valid point against
> prototype-based inheritance as it is provided by ECMAScript implementations.

Thank you for that valuable insight. I will assume the "you" does not
refer to me.

questorJs

unread,
Feb 15, 2008, 3:27:52 AM2/15/08
to

I absolutely agree with you on this one. The existence of constructor
functions confuses everything. When you come from the statically typed
world, like Java, they make some sort of sense. But the more you
learn, the more you find that your'e trying to do all sorts of
workarounds. I'm beginning to think that new object creation should be
wrapped into maker functions, since, lets face it, there's no proper
way to define an object template and how it inherits from other
objects/templates/classes/types or what you like to call it. For many,
I believe this is the greates hurdle. So many different ways to create
objects, and if your'e not careful, you'll introduce strange and
wonderful faults into your applications.

helgi

Lasse Reichstein Nielsen

unread,
Feb 15, 2008, 4:04:48 PM2/15/08
to
Joost Diepenmaat <jo...@zeekat.nl> writes:

> IMO what's actually confusing about prototypes in javascript is that the
> language tries to hide the prototypes behind constructor functions,
> which when taken at face value (i.e. when you're making assumptions
> based on the semantics of well known class-oriented systems) break at
> the point where you start using "class" inheritance, and *then* you have
> to re-think the way you're building objects. And then constructors
> become more and more useless. At least, that's what happened to me.

It happens to *lots* of people, probably most. Many never progress to
the point where the conflict between their internal model and the
actual model becomes too noticable to ignore.

> The strange thing is that a prototype system like javascript has is in
> principle much easier to comprehend (and implement) than systems where
> classes are special.

Maybe, maybe not. In the "real world"(TM) we think in both concrete
objects (that bird over there) and concepts (bird - something with
beak and wings). This matches the class based modelling approach
well.

When you use prototypical inheritance, you will often keep a mental
distinction between the prototype objects and "real" instance objects
- they are different kinds of objects, but there is no language support
to enforce the distinction. It's a simple programming model, but not
necessarily a simpler mental model. The class/instance distinction
is part of the inherent complexity of the description, and it will
show up, whether your language supports it or not.

/L
--

Lasse Reichstein Nielsen - l...@hotpop.com

Lasse Reichstein Nielsen

unread,
Feb 15, 2008, 4:12:10 PM2/15/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Joost Diepenmaat wrote:

>> Which should scare everybody enough while still being technically
>> correct :-)

> You should remove the entire footnote as it is pure nonsense.

FWIW, I would also suggest removing it, but only because I think it
confuzes more than it helps. What it says is technically correct, but
the word "class" is used in a different meaning than in the paragraph
that the footnote is for. I.e., it's not really relevant for that
paragraph. Or perhaps it could just be reduced to "The ECMAScript
standard only uses the word 'class' in a different meaning than it is
used in class based object orientation."

John G Harris

unread,
Feb 15, 2008, 3:49:10 PM2/15/08
to
On Fri, 15 Feb 2008 at 01:19:43, in comp.lang.javascript, Joost
Diepenmaat wrote:
>RobG <rg...@iinet.net.au> writes:
>
>> On Feb 15, 12:26 am, questorJs <helgi.kristjans...@gmail.com> wrote:
>>> Interesting discussions, I must say. Prototypical inheritance is quite
>>> confusing in JavaScript.
>>
>> I don't think it's more confusing, just different. Most programmers
>> come to javascript from another language and probably already know
>> classical inheritance. They often assume javascript works the same
>> way.
>
>IMO what's actually confusing about prototypes in javascript is that the
>language tries to hide the prototypes behind constructor functions,
>which when taken at face value (i.e. when you're making assumptions
>based on the semantics of well known class-oriented systems) break at
>the point where you start using "class" inheritance, and *then* you have
>to re-think the way you're building objects. And then constructors
>become more and more useless. At least, that's what happened to me.

I don't understand why you don't like constructors. In Java and similar
languages the compiler writes part of the constructor's code. The
compiler makes sure that the constructor creates and initialises the
instance's ancestor properties.

But this is javascript. You have to do this work yourself as the
compiler won't do it for you. You have to call the ancestor
constructors, in non-constructor mode, yourself. Or you can duplicate
the code that does the job. (There's usually more than one way to do
anything in javascript).

Likewise, in Java etc the compiler makes sure that the instance can
access its methods and its ancestor methods. It does this in any way it
wants. The programmer doesn't need to know, and probably can't know.

Again, this is javascript, where you have to do it yourself. One obvious
way is to build a prototype chain with a layer of methods attached to
each prototype object. Each object in the chain has to be constructed of
course. The obvious way to do this is to have a constructor for that
particular kind of prototype. (Why are people so frightened of doing
this?)

All this is very tedious and annoying to code. On the other hand, it's
much the same each time and can be done while thinking about the
difficult bits you haven't done yet.


>The strange thing is that a prototype system like javascript has is in
>principle much easier to comprehend (and implement) than systems where
>classes are special.

Having to code it yourself with no help from the compiler means that you
end up with a much better idea of what's going on in the program. It
should also make it easier to understand what's happening in Java etc
where much is hidden from you. This is a Good Thing.

John
--
John Harris

Joost Diepenmaat

unread,
Feb 15, 2008, 4:26:18 PM2/15/08
to
Lasse Reichstein Nielsen <l...@hotpop.com> writes:

> Joost Diepenmaat <jo...@zeekat.nl> writes:
>> The strange thing is that a prototype system like javascript has is in
>> principle much easier to comprehend (and implement) than systems where
>> classes are special.
>
> Maybe, maybe not. In the "real world"(TM) we think in both concrete
> objects (that bird over there) and concepts (bird - something with
> beak and wings). This matches the class based modelling approach
> well.

I'm not sure that it's useful for a programmer to think in concepts vs
concrete objects like that or that classes are really the right way to
model concepts. But I agree that they seem to make some kind of
intuitive sense. I still maintain that prototypes are actually simpler
to understand, though. I think that because prototypes need much less
"infrastructure" to make them work it turns out that in javascript at
least, you end up writing mechanisms yourself that you might take for
granted in, say, Java.

> When you use prototypical inheritance, you will often keep a mental
> distinction between the prototype objects and "real" instance objects
> - they are different kinds of objects, but there is no language support
> to enforce the distinction. It's a simple programming model, but not
> necessarily a simpler mental model. The class/instance distinction
> is part of the inherent complexity of the description, and it will
> show up, whether your language supports it or not.

That's true. There are definitely lots of problems where you actually
want something /like/ a class-based system. But from my experience, the
main trouble with javascript prototypes (and solved by traditional class
systems) in those cases is that of initialisation of instance
properties. Most class based systems solve that problem by calling all
initializers of all (super-)classes for each instantiation
automatically. Javascript forces you do it explictly (but gives quite a
bit flexibility in return). I don't know what (if anything) other
prototype-based languages provide to make this issue easier to deal
with.

Joost Diepenmaat

unread,
Feb 15, 2008, 4:38:45 PM2/15/08
to
John G Harris <jo...@nospam.demon.co.uk> writes:

> I don't understand why you don't like constructors. In Java and similar
> languages the compiler writes part of the constructor's code. The
> compiler makes sure that the constructor creates and initialises the
> instance's ancestor properties.

It's not that I don't like constructors, it's that I don't like that I
/have/ to use them, when I usually can't use them for actually
initializing the objects correctly, so I end up with a load of empty
constructors. They just seem like more or less useless fluff that could
have been avoided by just providing direct access to the prototype.

[ ... ]

> Again, this is javascript, where you have to do it yourself. One obvious
> way is to build a prototype chain with a layer of methods attached to
> each prototype object. Each object in the chain has to be constructed of
> course. The obvious way to do this is to have a constructor for that
> particular kind of prototype. (Why are people so frightened of doing
> this?)

Something is not quite as straightforward here as you make it seem. I'll
have to think about this and try some stuff.

[ ... ]

>>The strange thing is that a prototype system like javascript has is in
>>principle much easier to comprehend (and implement) than systems where
>>classes are special.
>
> Having to code it yourself with no help from the compiler means that you
> end up with a much better idea of what's going on in the program. It
> should also make it easier to understand what's happening in Java etc
> where much is hidden from you. This is a Good Thing.

100% agreed.

Thomas 'PointedEars' Lahn

unread,
Feb 15, 2008, 5:12:52 PM2/15/08
to
Lasse Reichstein Nielsen wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Joost Diepenmaat wrote:
>>> Which should scare everybody enough while still being technically
>>> correct :-)
>> You should remove the entire footnote as it is pure nonsense.
>
> FWIW, I would also suggest removing it, but only because I think it
> confuzes more than it helps.

It merely provides the author's misconceptions about the language.

> What it says is technically correct,

No, it's not. There are no "system-defined classes" (in whatever meaning of
the word), and a conforming ECMAScript implementation has to provide the
built-in objects which names are merely designated by the value of their
internal [[Class]] property.

> but the word "class" is used in a different meaning than in the paragraph
> that the footnote is for. I.e., it's not really relevant for that
> paragraph.

As I said, the paragraph as it now is, is pure nonsense.

> Or perhaps it could just be reduced to "The ECMAScript standard only uses
> the word 'class' in a different meaning than it is used in class based
> object orientation."

Has anyone of you actually checked that? Well, I did.

The ECMAScript Language Specification (Edition 3 Final) uses the word
"class" only in the following contexts and in its corresponding meaning:

| 15.4 Array Objects
|
| Array objects give special treatment to a certain class of property names.
| [...]

| 15.4.4.11 Array.prototype.sort (comparefn)
|
| [...]
| NOTE The above conditions are necessary and sufficient to ensure that
| comparefn divides the set S into equivalence classes and that these
| equivalence classes are totally ordered.

| 15.10 RegExp (Regular Expression) Objects
|
| Atom ::
| PatternCharacter
| .
| \ AtomEscape
| CharacterClass
|
| CharacterClassEscape :: one of
| dDsSwW
|
| CharacterClass ::
| [ [lookahead ∉ {^}] ClassRanges ]
| [^ ClassRanges ]
|
| [aso.]

| 15.11 Error Objects
|
| Instances of Error objects are thrown as exceptions when runtime errors
| occur. The Error objects may also serve as base objects for user-defined
| exception classes.

| A Grammar Summary
|
| A.1 Lexical Grammar
| [...]
| FutureReservedWord :: one of See section 7.5.3
| abstract enum int short
| boolean export interface static
| byte extends long super
| char final native synchronized
| class float package throws
|
| [...]
| A.6 Universal Resource Identifier Character Classes
|
| [aso., see 15.10]

Everything else are all occurrences of "[[Class]]" which is clearly and
always referring to the internal [[Class]] property value (a string of
characters) that is purely (required as a) a specification mechanisms.
(The property name is merely unfortunate, to say the least.)

It is therefore simply ridiculous to conclude that there were
"system-defined classes" in ECMAScript or classes at all (as in "A user
cannot add a new class, though the host system may define more."). It is
even more ridiculous to say that these or the values for internal [[Class]]
property of the built-in objects "are not required to exist at all".

The Specification makes that one thing very clear:

| 4.2.1 Objects
|
| ECMAScript does not contain proper classes such as those in C++,
| Smalltalk, or Java, but rather, supports constructors which create objects
| by executing code that allocates storage for the objects and initialises
| all or part of them by assigning initial values to their properties.

One can only wonder what part of "does not contain [...] classes" he did not
get yet.


PointedEars

Joost Diepenmaat

unread,
Feb 15, 2008, 5:52:00 PM2/15/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

> Lasse Reichstein Nielsen wrote:
>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>> Joost Diepenmaat wrote:
>>>> Which should scare everybody enough while still being technically
>>>> correct :-)
>>> You should remove the entire footnote as it is pure nonsense.
>>
>> FWIW, I would also suggest removing it, but only because I think it
>> confuzes more than it helps.
>
> It merely provides the author's misconceptions about the language.
>
>> What it says is technically correct,
>
> No, it's not. There are no "system-defined classes" (in whatever meaning of
> the word), and a conforming ECMAScript implementation has to provide the
> built-in objects which names are merely designated by the value of their
> internal [[Class]] property.

As far as I can see the [[class]] property is there as a short-cut for
implementors to make comparisons and other operators behave more
efficiently. In other words, it's there as a "class-like" system for
types that may be implemented in all kinds of ways.

> As I said, the paragraph as it now is, is pure nonsense.

Confusing and maybe misguided, but it ain't nonsense. Your tendency to
treat people who write things that you don't 100% agree with as idiots
tends to overshadow your usually correct technical assessments

[ ... ]

> (The property name is merely unfortunate, to say the least.)

I sort of agree, but I think there isn't really a good word to use,
except maybe "type", which would probably be even more confusing.

> It is therefore simply ridiculous to conclude that there were
> "system-defined classes" in ECMAScript or classes at all (as in "A user
> cannot add a new class, though the host system may define more.").

As far as implementations go, it's not at all unreasonable to assume
that there are such class-like things and the fact that they're
mentioned in the specs as such is - I assume - no acccident. They are
not /required/ to exist in any way, which is what the rest of the
paragraph is about.

> It is even more ridiculous to say that these or the values for
> internal [[Class]] property of the built-in objects "are not required
> to exist at all".

Of course that part is true. It's a direct consequence of the description
of internal properties.

John G Harris

unread,
Feb 16, 2008, 3:44:54 PM2/16/08
to
On Fri, 15 Feb 2008 at 22:38:45, in comp.lang.javascript, Joost
Diepenmaat wrote:
>John G Harris <jo...@nospam.demon.co.uk> writes:
>
>> I don't understand why you don't like constructors. In Java and similar
>> languages the compiler writes part of the constructor's code. The
>> compiler makes sure that the constructor creates and initialises the
>> instance's ancestor properties.
>
>It's not that I don't like constructors, it's that I don't like that I
>/have/ to use them, when I usually can't use them for actually
>initializing the objects correctly, so I end up with a load of empty
>constructors. They just seem like more or less useless fluff that could
>have been avoided by just providing direct access to the prototype.
<snip>

I'm puzzled. The work of building your new object will obviously be
packaged in a function, either for tidiness or because you believe in
encapsulation. How do you describe this function : a user-constructor,
an outer-constructor? It has to be something like that. I'm puzzled
because I can't see which part of that work couldn't be put inside the
javascript constructor.

I'm also puzzled by your reference to 'the prototype'. Which meaning of
the word 'prototype' are you using?


>> Again, this is javascript, where you have to do it yourself. One obvious
>> way is to build a prototype chain with a layer of methods attached to
>> each prototype object. Each object in the chain has to be constructed of
>> course. The obvious way to do this is to have a constructor for that
>> particular kind of prototype. (Why are people so frightened of doing
>> this?)
>
>Something is not quite as straightforward here as you make it seem. I'll
>have to think about this and try some stuff.

<snip>

My web site has an example of what I'm thinking here :

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

It's very straightforward. It's also very tedious :-(


John
--
John Harris

Joost Diepenmaat

unread,
Feb 16, 2008, 5:03:35 PM2/16/08
to
John G Harris <jo...@nospam.demon.co.uk> writes:

> On Fri, 15 Feb 2008 at 22:38:45, in comp.lang.javascript, Joost
> Diepenmaat wrote:
>>John G Harris <jo...@nospam.demon.co.uk> writes:
> I'm puzzled. The work of building your new object will obviously be
> packaged in a function, either for tidiness or because you believe in
> encapsulation. How do you describe this function : a user-constructor,
> an outer-constructor? It has to be something like that. I'm puzzled
> because I can't see which part of that work couldn't be put inside the
> javascript constructor.

The objects will be created in a function, yes. But when you're using
prototypes to inherit behaviour, you often can't use the super-object's
constructors to initialize instance properties since that would set the
properties of the prototype instead. What you then end up with is an
empty constructor with a .prototype that takes care of the shared
properties (usually just the methods, possibly some default
values). Plus a function (or method) to set the properties of the
instance that can be called when you're instantiating the sub object.

> I'm also puzzled by your reference to 'the prototype'. Which meaning of
> the word 'prototype' are you using?

The internal [[prototype]].

>>> Again, this is javascript, where you have to do it yourself. One obvious
>>> way is to build a prototype chain with a layer of methods attached to
>>> each prototype object. Each object in the chain has to be constructed of
>>> course. The obvious way to do this is to have a constructor for that
>>> particular kind of prototype. (Why are people so frightened of doing
>>> this?)
>>
>>Something is not quite as straightforward here as you make it seem. I'll
>>have to think about this and try some stuff.
> <snip>
>
> My web site has an example of what I'm thinking here :
>
> <URL:http://www.jgharris.demon.co.uk/jsfeats/JSfeats.html#seca1p1>
>
> It's very straightforward. It's also very tedious :-(

I see where my confusion was coming from. You're using twice as many
constructors as I do: one constructor to initialize the prototype and
another to initialize the instance, for each "type" of object. I
generally write the instance initializers as methods of the respecive
[[prototypes]] instead. I don't have anything lying around to show what
I mean right now...

Thomas 'PointedEars' Lahn

unread,
Feb 17, 2008, 5:34:12 AM2/17/08
to
Joost Diepenmaat wrote:
> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Lasse Reichstein Nielsen wrote:
>>> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>>>> Joost Diepenmaat wrote:
>>>>> Which should scare everybody enough while still being technically
>>>>> correct :-)
>>>> You should remove the entire footnote as it is pure nonsense.
>>> FWIW, I would also suggest removing it, but only because I think it
>>> confuzes more than it helps.
>> It merely provides the author's misconceptions about the language.
>>
>>> What it says is technically correct,
>> No, it's not. There are no "system-defined classes" (in whatever meaning of
>> the word), and a conforming ECMAScript implementation has to provide the
>> built-in objects which names are merely designated by the value of their
>> internal [[Class]] property.
>
> As far as I can see the [[class]] property is there as a short-cut for
> implementors to make comparisons and other operators behave more
> efficiently. In other words, it's there as a "class-like" system for
> types that may be implemented in all kinds of ways.

You have not said or written "class-like" at all.

>> As I said, the paragraph as it now is, is pure nonsense.
>
> Confusing and maybe misguided, but it ain't nonsense. Your tendency to
> treat people who write things that you don't 100% agree with as idiots
> tends to overshadow your usually correct technical assessments

You have stated that there were "system-defined classes" while referring to
the [[Class]] property. There are _not_. Admitting that error and your
misconception instead of blaming others of misunderstanding you, would help
a great deal to increase your credibility.

>> It is therefore simply ridiculous to conclude that there were
>> "system-defined classes" in ECMAScript or classes at all (as in "A user
>> cannot add a new class, though the host system may define more.").
>
> As far as implementations go, it's not at all unreasonable to assume
> that there are such class-like things and the fact that they're
> mentioned in the specs as such is - I assume - no acccident. They are
> not /required/ to exist in any way, which is what the rest of the
> paragraph is about.

You miss the point.

>> It is even more ridiculous to say that these or the values for
>> internal [[Class]] property of the built-in objects "are not required
>> to exist at all".
>
> Of course that part is true. It's a direct consequence of the description
> of internal properties.

It is only true because a conclusion ("system-defined classes a not required
to exist at all") drawn from a false supposition ("there are system-defined
classes") is always true.

Joost Diepenmaat

unread,
Feb 17, 2008, 7:30:24 AM2/17/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

>> As far as I can see the [[class]] property is there as a short-cut for
>> implementors to make comparisons and other operators behave more
>> efficiently. In other words, it's there as a "class-like" system for
>> types that may be implemented in all kinds of ways.
>
> You have not said or written "class-like" at all.

Ok, if *that's* what you're objecting to, fine. You're right.

Joost Diepenmaat

unread,
Feb 17, 2008, 8:03:32 AM2/17/08
to

I updated the foot note.

http://joost.zeekat.nl/constructors-considered-mildly-confusing.html#1_

If anyone still objects to its content, please let me know why.

Thomas 'PointedEars' Lahn

unread,
Feb 17, 2008, 8:27:58 AM2/17/08
to
Joost Diepenmaat wrote:
> I updated the foot note.
>
> http://joost.zeekat.nl/constructors-considered-mildly-confusing.html#1_
>
> If anyone still objects to its content, please let me know why.

You state in the section "Objects and methods":

| For most intents, javascript does not have classes. 1]

As pointed out by several people here already, that is wrong. For
*all* intents, javascript (if we assume you use that term to refer
to implementations of the ECMAScript Specification up to Edition 3
by that, see below) does not have classes.

In the corresponding footnote you state:

| The specification mentions that every object should have an internal
| [[Class]] property. [...]

However, the ECMAScript Language Specification, Edition 3 Final, states in
its section 8.6.2:

| Every object (including host objects) must implement the [[Prototype]] and
| [[Class]] properties [...]
|
| The value of the [[Class]] property of a host object may be any value,
| even a value used by a built-in object for its [[Class]] property.
| The value of a [[Class]] property is used internally to distinguish
| different kinds of built-in objects. [...]

It is very important to recognize the key words "must", "should", and "may"
in a technical specification for what they are, and use them accordingly in
a technical discussion as they indicate the requirement level of a feature
(and so they are often emphasized with being written in all-uppercase).
"Must" indicates an absolute requirement for conformance, "should" indicates
a strong recommendation, and "may" indicates a conforming possibility that
is not necessarily a recommended one.


Your essay also lacks the necessary differentiation between the ECMAScript
Language Specification, one possible implementation of it,
Netscape/Mozilla.org JavaScript, and other implementations like Microsoft
JScript. On several occasions you mention a "Javascript" language and a
"javascript interpreter", however there are no such things. I would
consider the recognition of this difference to be a key point in
understanding the kind of programming that is discussed here.


HTH

PointedEars

Joost Diepenmaat

unread,
Feb 17, 2008, 9:33:42 AM2/17/08
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:
> You state in the section "Objects and methods":
>
> | For most intents, javascript does not have classes. 1]
>
> As pointed out by several people here already, that is wrong. For
> *all* intents, javascript (if we assume you use that term to refer
> to implementations of the ECMAScript Specification up to Edition 3
> by that, see below) does not have classes.

You're right. I missed that point.

> In the corresponding footnote you state:
>
> | The specification mentions that every object should have an internal
> | [[Class]] property. [...]

[...]

> It is very important to recognize the key words "must", "should", and "may"
> in a technical specification for what they are, and use them accordingly in
> a technical discussion as they indicate the requirement level of a feature
> (and so they are often emphasized with being written in all-uppercase).
> "Must" indicates an absolute requirement for conformance, "should" indicates
> a strong recommendation, and "may" indicates a conforming possibility that
> is not necessarily a recommended one.

Fair point.

> Your essay also lacks the necessary differentiation between the ECMAScript
> Language Specification, one possible implementation of it,
> Netscape/Mozilla.org JavaScript, and other implementations like Microsoft
> JScript. On several occasions you mention a "Javascript" language and a
> "javascript interpreter", however there are no such things. I would
> consider the recognition of this difference to be a key point in
> understanding the kind of programming that is discussed here.

In the the text, with "Javascript" and "Javascript interpreter" I meant
to refer to the various implementations of Ecma-262 3rd edition. I
should probably make that explicit.

> HTH

That was useful. Thanks.

John G Harris

unread,
Feb 17, 2008, 4:45:56 PM2/17/08
to
On Sat, 16 Feb 2008 at 23:03:35, in comp.lang.javascript, Joost
Diepenmaat wrote:
>John G Harris <jo...@nospam.demon.co.uk> writes:
>
>> On Fri, 15 Feb 2008 at 22:38:45, in comp.lang.javascript, Joost
>> Diepenmaat wrote:
>>>John G Harris <jo...@nospam.demon.co.uk> writes:
>> I'm puzzled. The work of building your new object will obviously be
>> packaged in a function, either for tidiness or because you believe in
>> encapsulation. How do you describe this function : a user-constructor,
>> an outer-constructor? It has to be something like that. I'm puzzled
>> because I can't see which part of that work couldn't be put inside the
>> javascript constructor.
>
>The objects will be created in a function, yes. But when you're using
>prototypes to inherit behaviour, you often can't use the super-object's
>constructors to initialize instance properties since that would set the
>properties of the prototype instead. What you then end up with is an
>empty constructor with a .prototype that takes care of the shared
>properties (usually just the methods, possibly some default
>values). Plus a function (or method) to set the properties of the
>instance that can be called when you're instantiating the sub object.

In javascript there is usually more than one way of doing it, whatever
'it' might be. Even so, I think that here there is a danger of two
different jobs being tangled together in a way that causes problems.

One job is to build a prototype chain for use by all the objects of this
kind. This is done once, before any of the objects are created. (You
could give each object its own personal prototype chain, but why would
you?)

The other job is to give to each object of this kind its own personal
initial data values and a pointer to the shared prototype chain. This is
done many times, at each object creation.

These are separate jobs, done at different times. They shouldn't
overlap, even if they are packaged inside one data structure. If they
don't overlap then ancestor jobs don't overlap either, so no problems
with inheritance.


<snip>

>>>> Again, this is javascript, where you have to do it yourself. One obvious
>>>> way is to build a prototype chain with a layer of methods attached to
>>>> each prototype object. Each object in the chain has to be constructed of
>>>> course. The obvious way to do this is to have a constructor for that
>>>> particular kind of prototype. (Why are people so frightened of doing
>>>> this?)
>>>
>>>Something is not quite as straightforward here as you make it seem. I'll
>>>have to think about this and try some stuff.
>> <snip>
>>
>> My web site has an example of what I'm thinking here :
>>
>> <URL:http://www.jgharris.demon.co.uk/jsfeats/JSfeats.html#seca1p1>
>>
>> It's very straightforward. It's also very tedious :-(
>
>I see where my confusion was coming from. You're using twice as many
>constructors as I do: one constructor to initialize the prototype and
>another to initialize the instance, for each "type" of object. I
>generally write the instance initializers as methods of the respecive
>[[prototypes]] instead. I don't have anything lying around to show what
>I mean right now...

It's not really two constructors. Javascript has only one way to attach
an object to the front of a prototype chain in order to make the chain
longer : that's to use 'new' with a user-defined function. Call this an
extender function, then you'll remember that there are two kinds of
creation functions, one for each job (see above).


John
--
John Harris

Joost Diepenmaat

unread,
Feb 18, 2008, 2:56:37 AM2/18/08
to
John G Harris <jo...@nospam.demon.co.uk> writes:

[ ... ]

> These are separate jobs, done at different times. They shouldn't
> overlap, even if they are packaged inside one data structure. If they
> don't overlap then ancestor jobs don't overlap either, so no problems
> with inheritance.

Completely agreed.

> It's not really two constructors. Javascript has only one way to
> attach an object to the front of a prototype chain in order to make
> the chain longer : that's to use 'new' with a user-defined
> function. Call this an extender function, then you'll remember that
> there are two kinds of creation functions, one for each job (see
> above).

Right. For most of the code where I use a prototype chain containing
more than one or two custom prototypes I've found that having the
constructor abstracted away completely (only using automatically
generated empty constructors) made the code a lot simpler to write. In
the end though, I think it's mostly a question of taste.

John G Harris

unread,
Feb 18, 2008, 3:26:16 PM2/18/08
to
On Mon, 18 Feb 2008 at 08:56:37, in comp.lang.javascript, Joost
Diepenmaat wrote:

<snip>


>Right. For most of the code where I use a prototype chain containing
>more than one or two custom prototypes I've found that having the
>constructor abstracted away completely (only using automatically
>generated empty constructors) made the code a lot simpler to write. In
>the end though, I think it's mostly a question of taste.

Yes. There are several ways of doing it.

Therefore, your web page should make it clear that your complaints about
javascript are aimed at your way of doing it. Other people have no need
to complain.

John
--
John Harris

Joost Diepenmaat

unread,
Feb 18, 2008, 4:01:43 PM2/18/08
to
John G Harris <jo...@nospam.demon.co.uk> writes:

> Yes. There are several ways of doing it.
>
> Therefore, your web page should make it clear that your complaints about
> javascript are aimed at your way of doing it. Other people have no need
> to complain.

Why would I do that?

On that page I'm pointing out some potentially confusing things that can
happen with constructors. *You* may not find them confusing, but at
least some people would - they confused me when I first ran into them
and they confused the person who originally started this thread - so I
tried to explain what's happening as clearly and objectively as I could.

I do have some complaints about the whole constructor-prototype idea in
general and I have sketched out some ways that I like to work around
them, but none of that is on that page, or even site. Most of it in this
thread, which people can read for themselves.

John G Harris

unread,
Feb 19, 2008, 3:38:47 PM2/19/08
to

I'll just remind you of how you introduced us to that web page :

<quote>
Just to give you some examples of what can go wrong with the IMO nasty
"new constructor()" syntax:
</quote>

John
--
John Harris

Joost Diepenmaat

unread,
Feb 19, 2008, 3:54:46 PM2/19/08
to
John G Harris <jo...@nospam.demon.co.uk> writes:

> On Mon, 18 Feb 2008 at 22:01:43, in comp.lang.javascript, Joost
> Diepenmaat wrote:
>>John G Harris <jo...@nospam.demon.co.uk> writes:
>>
>>> Yes. There are several ways of doing it.
>>>
>>> Therefore, your web page should make it clear that your complaints about
>>> javascript are aimed at your way of doing it. Other people have no need
>>> to complain.

> I'll just remind you of how you introduced us to that web page :


>
> <quote>
> Just to give you some examples of what can go wrong with the IMO nasty
> "new constructor()" syntax:
> </quote>
>

What part of IMO do you not understand?

Joost Diepenmaat

unread,
Feb 19, 2008, 4:08:08 PM2/19/08
to

Just FYI: the introduction to that page was at msg-id
<87wspbb...@zeekat.nl>, in this thread, about 8 hours earlier, you
may have missed it then:

"I had some free time this weekend to do a somewhat extensive write-up
about this problem. It may be of interested to some people.

http://joost.zeekat.nl/constructors-considered-mildly-confusing.html

Feel free to ask questions or comment if it seems wrong or
incomprehensible."

Note, the "this problem" refers to the OP of this thread.

0 new messages