question about Crockford essay - assigning methods to an object's prototype

L

lkrubner

I'm reading an essay, I think one of Crockford's, and it has this
example in it:

function Demo() { }
Demo.prototype = new Ancestor();
Demo.prototype.foo = function () { } ;

Does Ancestor now have a function called foo?

What if I have 5 different objects, all descended from Ancestor? Do
they all now acquire a method named foo, if I just once assign a method
like this?
 
T

Thomas 'PointedEars' Lahn

function Demo() { }
Demo.prototype = new Ancestor();
Demo.prototype.foo = function () { } ;

Does Ancestor now have a function called foo?

No, objects derived from Demo have. Which can be easily tested with

alert(Ancestor.foo);
alert(Ancestor.prototype.foo);
alert(Demo.foo);
alert(Demo.prototype.foo);
alert(new Ancestor().foo);
alert(new Demo().foo);

and the like.
What if I have 5 different objects, all descended from Ancestor?
Do they all now acquire a method named foo, if I just once assign
a method like this?

No. Assigning (rather: defining) a method like this affects the modified
prototype (Demo) and objects derived from it, not its prototype (Ancestor)
or objects derived from that.


PointedEars
 
L

lkrubner

Thomas said:
No, objects derived from Demo have. Which can be easily tested

Sorry for being stupid, but how is this:

Demo.prototype.foo = function () { } ;

different from this:

Demo.foo = function () { } ;

In both cases Demo ends up with a method called foo, yes?

I guess I don't understand the language but this line:

Demo.prototype = new Ancestor();

Looks like it's saying "Demo's prototype is Ancestor."

And this line:

Demo.prototype.foo = function () { } ;

looks like its saying "We will now assign a function foo to the the
prototype of Demo, which is Ancestor."
 
L

Lasse Reichstein Nielsen

Sorry for being stupid, but how is this:

Demo.prototype.foo = function () { } ;

different from this:

Demo.foo = function () { } ;

In both cases Demo ends up with a method called foo, yes?

No.

Demo is a function, used as a constructor function, and therefore
an object (all functions are objects and can have properties).

In the latter case, Demo itself has a method (a function property)
called "foo".

In the former, Demo has no property called foo, but the object
referenced by Demo.prototype does. That means that all objects created
by "new Demo()" will have an method called "foo", inherited from its
prototype.
I guess I don't understand the language but this line:

Demo.prototype = new Ancestor();

Looks like it's saying "Demo's prototype is Ancestor."

It reads like that, but it's not exactly what it means.

You are confusing the function "Ancestor" and the (non-function)
objects created from it using "new Ancestor()".

Constructor functions, like Demo and Ancestor here, are merely a
way to perform prototype inheritance between objects.

Each object in Javascript has another object as its prototype [1], and
it inherits all properties of that prototype object that isn't hidden
by a property on the object itself. Since the prototype itself is an
object and has a prototype, we talk about the prototype *chain* of an
object.

When writing "new SomeFunction()", what happens is that a new object
is created, and its prototype object is set to the object referenced
by SomeFunction.prototype at that time. After that, the body of
SomeFunction is executed with "this" referring to the new object.
After this, SomeFunction has nothing more to do with the new object,
it is just used for initialization.

So "Demo.prototype = new Ancestor()" really means:
Create a new object inheriting from Ancestor.prototype and
initialized by running Ancestor (and then we can forget about
Ancestor).
Then set that object as the prototype of objects created using "new
Demo()".
And this line:

Demo.prototype.foo = function () { } ;

looks like its saying "We will now assign a function foo to the the
prototype of Demo, which is Ancestor."

We will now assign a function to the prototype of objects created from
Demo (by "new Demo()"), which was originally created using Ancestor.


Now for the fun. Try running this and understand the results :)
---
function Foo(){};
function Bar(){};
var foo = new Foo();
var bar = new Bar();
Foo.prototype.baz = 42;
alert(foo.baz); // alerts 42! the prototype link is live
Bar.prototype = Foo.prototype;
alert(bar.baz); // alerts undefined. Inheritance is between objects,
// the function is not important afterwards.
alert(foo instanceof Bar); // alerts true - really tests if
// Bar.prototype is in foo's prototype chain.
// Again, the function itself is not important
 
M

Michael Winter

On 08/11/2005 22:50, (e-mail address removed) wrote:

[snip]
Sorry for being stupid, but how is this:

Demo.prototype.foo = function () { } ;

different from this:

Demo.foo = function () { } ;

In both cases Demo ends up with a method called foo, yes?

Lasse described the difference with regard to inheritance. With the
latter, the Demo constructor has a property, foo, but instances will not:

function Demo() {}
Demo.foo = function() {};

var myInstance = new Demo();

Demo.foo(); /* OK */
myInstance.foo(); /* Run-time error: foo is not a function */

Another important consideration is that with the former, all instances
of Demo will share the /same/ foo method:

/* Returns a function object with the
* variable, calls, in its scope chain.
*
* Multiple calls to createMethod will
* create new function objects, each
* with their own variable, calls.
*/
function createMethod() {
var calls = 0;

return function() {
return ++calls;
};
}


function Demo() {}
Demo.prototype.foo = createMethod();

var myInstance1 = new Demo(),
myInstance2 = new Demo();

myInstance1.foo(); /* 1 */
myInstance1.foo(); /* 2 */

myInstance2.foo(); /* 3 (Even though it's a
* different instance!)
*/

Compare that to a method added within the constructor function:

function Demo() {
this.foo = createMethod();
}

var myInstance1 = new Demo(),
myInstance2 = new Demo();

myInstance1.foo(); /* 1 */
myInstance1.foo(); /* 2 */

myInstance2.foo(); /* 1 */
I guess I don't understand the language but this line:

Demo.prototype = new Ancestor();

Looks like it's saying "Demo's prototype is Ancestor."

An instance of Ancestor.
And this line:

Demo.prototype.foo = function () { } ;

looks like its saying "We will now assign a function foo to the the
prototype of Demo, which is Ancestor."

Again, "...which is an instance of Ancestor." The Demo prototype object
is a separate, unique instance. /It/ will be changed, but Ancestor will not.

Mike
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top