Prototype Convention?

M

Martin Rinehart

Is there a convention for setting up a prototype?

You could write:

Foo.prototype = {};
Foo.prototype.toString = function ...
Foo.prototype.other = ...

or you could write:

Foo.prototype = {
toString: function ...,
other:...
};
 
J

John G Harris

Is there a convention for setting up a prototype?

You could write:

Foo.prototype = {};
Foo.prototype.toString = function ...
Foo.prototype.other = ...

or you could write:

Foo.prototype = {
toString: function ...,
other:...
};

A third way is to treat it as an object that needs to be constructed
just like any other object :
Foo.prototype = new protoFoo();
Now the code to make the prototype is neatly packaged inside the
protoFoo code, and your prototype object can have any prototype you
choose.

John
 
J

John G Harris

In both cases the prototype object attached to Foo is an ordinary
object. But it might be 'an instance of another class'.

You can't get that with the second approach (an object literal) but you
can with the first:
Foo.prototype = new Bar();

But note that Foo.prototype now holds a Bar object's data. That data is
irrelevant at best, and thoroughly confusing at worst.

John
 
L

Lasse Reichstein Nielsen

Martin Rinehart said:
Is there a convention for setting up a prototype?

You could write:

Foo.prototype = {};
Foo.prototype.toString = function ...
Foo.prototype.other = ...

or you could write:

Foo.prototype = {
toString: function ...,
other:...
};

The former has the advantage of always working.
If an object has already been created from the Foo function, changing
the prototype property will not affect old objects, but extending the
existing prototype object will add the functions to the old objects
as well.
The "constructor" property on the original Foo.prototype needs to be
copied too, if you replace the Foo.prototype object. Who knows which
frameworks might expect it to be there.
Likewise for properties that someone else has already extended the
original prototype with.

All "problems" that might not apply in any particular case, but you
have to ensure that (e.g., by only changing the prototype object
immediately after creating the function, and remember to set the
"constructor" property).

/L
 
M

Martin Rinehart

John said:
But note that Foo.prototype now holds a Bar object's data. That data is
irrelevant at best, and thoroughly confusing at worst.

Unless foo is intended to extend bar.
 
M

Martin Rinehart

Jonathan said:
This is nice. I like the consistency - "constructed just like any other
object".

To expand, so you write
===
var protoFoo = function(){

this.toString = function(){
// code
};
}

protoFoo.prototype = new Object(); // Or whatever.
===

Of course, once you've done
Foo.prototype = new protoFoo();
you can if you wish discard protoFoo. If you do, then protoFoo is what
I'd like to call a "use once object initialiser".
 
T

Thomas 'PointedEars' Lahn

Martin said:
Is there a convention for setting up a prototype?

Yes, there is. This is a *news*group; please search before you post.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Jonathan said:
Good point. You really need an uninitialized 'instance of Bar', which
you can get (I saw this idea in Cockcroft's Good Parts book) using:
var F = function(){};
F.prototype = Bar.prototype;
Foo.prototype = new F(); // An 'uninitialised instance of Bar'.

Perhaps I should have mentioned something like this when comparing the
two approaches put forward by the original poster.

This is a *news*group. Google for clone() and inheritFrom().


PointedEars
 
T

Thomas 'PointedEars' Lahn

Lasse said:
The former has the advantage of always working.

There are no differences in semantics or compatibility between the two
approaches *at all*.


PointedEars
 
L

Lasse Reichstein Nielsen

Thomas 'PointedEars' Lahn said:
There are no differences in semantics or compatibility between the two
approaches *at all*.

Except the ones I *actually listed*?

All it takes is for someone to be able to change the original
prototype, or get a reference to it, before you get to do anything,
then there is a lot of difference between updating the existing one or
replacing it.

If that doesn't apply, great: Use whatever feels best.


/L
 
J

Joost Diepenmaat

Lasse Reichstein Nielsen said:
Except the ones I *actually listed*?

All it takes is for someone to be able to change the original
prototype, or get a reference to it, before you get to do anything,
then there is a lot of difference between updating the existing one or
replacing it.

If that doesn't apply, great: Use whatever feels best.

Thomas is right. You seem to have missed that both posted variants
assign to Foo.prototype
 
J

John G Harris

This is a *news*group.

The word "news" was chosen unwisely when Usenet was invented, as you
very well know.

Google for clone() and inheritFrom().

The identifier "clone" has been used by thousands of programmers. Which
crappy library/book are you referring to ?

John
 
J

John G Harris

Unless foo is intended to extend bar.

No, the foo prototype is intended to extend the bar *prototype*.

Usually, prototype objects hold read-only properties, unless you're
doing something really tricky.

Usually, ordinary objects hold read-write properties, unless you're
convinced you won't make the mistake of writing to a property that is
designed to be read-only.

Thus, usually, prototype objects hold function objects (the methods) and
ordinary objects hold instance data (strings, numbers, simple objects,
etc).

John
 
D

David Mark

Thomas is right. You seem to have missed that both posted variants
assign to Foo.prototype

No, the first example augmented the existing prototype. The second
replaced it wholesale.

[snip]
 
J

Joost Diepenmaat

David Mark said:
No, the first example augmented the existing prototype. The second
replaced it wholesale.

Quoted from the post:

Foo.prototype = {};
Foo.prototype.toString = function ...
Foo.prototype.other = ...

or you could write:

Foo.prototype = {
toString: function ...,
other:...
};
 
T

Thomas 'PointedEars' Lahn

David said:
No, the first example augmented the existing prototype. The second
replaced it wholesale.

You are mistaken. It is easy to miss, but the empty Object literal (`{}')
creates a *new* Object object and assigns a reference to it to Foo.prototype
as well as the non-empty one (`{toString: ...}') does.

If that first assignment was omitted from the first example, then you and
Lasse were right.

However, the pattern

Foo.prototype.toString = function ...
Foo.prototype.other = ...
...

as compared to

Foo.prototype = {
...
};

is also less efficient (because of repeated lookups) and slightly harder to
maintain (because of repeated identifiers). So, when keeping the existing
prototype object is desired, I use(d) a method to augment the prototype
object (or just any object) instead (see JSX:eek:bject.js:addProperties() [1],
comments welcome); other developers have devised their own methods to do
about the same, e.g. Douglas Crockford introduces the Function.method()
method in his inheritance and code reuse examples [2].


PointedEars
___________
[1] <http://pointedears.de/scripts/object.js>
[2] <http://javascript.crockford.com/inheritance.html>
 
D

David Mark

You are mistaken.  It is easy to miss, but the empty Object literal (`{}')
creates a *new* Object object and assigns a reference to it to Foo.prototype
as well as the non-empty one (`{toString: ...}') does.

Yes. Somehow I missed that first line.
If that first assignment was omitted from the first example, then you and
Lasse were right.

However, the pattern

  Foo.prototype.toString = function ...
  Foo.prototype.other = ...
  ...

as compared to

  Foo.prototype = {
    ...
  };

is also less efficient (because of repeated lookups) and slightly harder to
maintain (because of repeated identifiers).  So, when keeping the existing

Yes.

[snip]
 
T

Thomas 'PointedEars' Lahn

Thomas said:
[...] So, when keeping the existing prototype object is desired, I use(d)
a method to augment the prototype object (or just any object) instead
(see JSX:eek:bject.js:addProperties() [1], comments welcome); other
developers have devised their own methods to do about the same, e.g.
Douglas Crockford introduces the Function.method() method in his ^^^^^^^^^^^^^^^^^^^^^^^^
inheritance and code reuse examples [2].

Actually, that's the Function.prototype.swiss() method there. The way it
was augmented had me confused shortly :)

----- bite here -----
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};

// [...]

Function.method('swiss', function (parent) {
for (var i = 1; i < arguments.length; i += 1) {
var name = arguments;
this.prototype[name] = parent.prototype[name];
}
return this;
});
----- bite here -----


PointedEars
 
L

Lasse Reichstein Nielsen

Joost Diepenmaat said:
Thomas is right. You seem to have missed that both posted variants
assign to Foo.prototype

Argh. Correct, my bad.

/L
 
D

dhtml

Lasse said:
Argh. Correct, my bad.


Each user-defined function gets a prototype property for free, so you
don't need to define it.

function Wibbler() { }

Wibbler.prototype.getCalfMuscle = function() {
return this.gastrocnemius || this.soleus || this.tibia;
};

alert(new Wibbler().constructor); // Wibbler.

The new Wibbler's constructor property {DontEnum} exists on the
Wibbler's prototype property, as Wibbler.prototype.constructor.

This is explained in the section on creating Function objects:
http://bclary.com/2004/11/07/#a-13.2

An interesting side effect is that the common practice of replacing the
Function object's prototype property will result in object's getting the
constructor property from the new object. This can be shown in an example:

function Wibbler() { }
Wibbler.prototype = {};
alert(new Wibbler().constructor); // Object.

The new Wibbler's constructor is not found in wibbler.prototype
directly, but in the [[Prototype]] object for Wibbler.prototype.

So we can replace it:-

function Wibbler() { }
Wibbler.prototype = {};
Wibbler.prototype.constructor = Wibbler;
alert(new Wibbler().constructor); // Wibbler.

- but now it is enumerable -

var w = new Wibbler;
for(var p in w)
alert(p);

elerts "constructor"

Garrett
 

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
474,129
Messages
2,570,770
Members
47,326
Latest member
Itfrontdesk

Latest Threads

Top