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

J

John G Harris

Joost Diepenmaat wrote:


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.

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
 
R

ron.h.hall

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
 
J

Joost Diepenmaat

kj said:
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.
 
L

Lasse Reichstein Nielsen

Joost Diepenmaat said:
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.

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
 
J

Joost Diepenmaat

Lasse Reichstein Nielsen said:
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 :)
 
T

Thomas 'PointedEars' Lahn

Joost said:
Lasse Reichstein Nielsen said:
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.


PointedEars
 
J

Joost Diepenmaat

Thomas 'PointedEars' Lahn said:
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.
 
L

Lasse Reichstein Nielsen

Joost Diepenmaat said:
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 :)

/L
 
J

Joost Diepenmaat

Lasse Reichstein Nielsen said:
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 :)
 
T

Thomas 'PointedEars' Lahn

Joost said:
Lasse Reichstein Nielsen said:
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 :)

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


PointedEars
 
J

Joost Diepenmaat

Thomas 'PointedEars' Lahn said:
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.
 
T

Thomas 'PointedEars' Lahn

Joost said:
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.


PointedEars
 
J

Joost Diepenmaat

Thomas 'PointedEars' Lahn said:
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.
 
Q

questorJs

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
 
R

RobG

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.
 
J

Joost Diepenmaat

RobG said:
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.
 
T

Thomas 'PointedEars' Lahn

Joost said:
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
 
J

Joost Diepenmaat

Thomas 'PointedEars' Lahn said:
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.
 
Q

questorJs

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.

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top