This forum is now read-only. Please use our new forums! Go to forums

0 points
Submitted by Mark Cross
over 9 years

The purpose of prototype

Hello, could someone please confirm my understanding of the purpose of prototyping? Thank you all for an absolutely awesome resource here at CA!

Based on my limited understanding, I would use prototype to extend a class with a function that doesn’t need to be recreated with each new instance of the class but instead the method (or property?) could be used over and over from just the single (extended) instance? Is that anywhere close to accurate?

Thanks! Any help is appreciated!

Answer 54f0550886f5528614001884

8 votes

Permalink

@Viggie, Never a dumb question. It comes up often so you needn’t feel alone. It’s good of you to ask so you get the help you need when you need it. I’ll make an attempt to give you an answer, but know that there are really good answers to this same question in many threads of this Q&A. Hope you’ll dig around and discover them.

Q: “…why would we use prototype instead of just adding the function into the object constructor?”

A: Efficiency and conservative use of memory resources.

We all have our own telephone, but we don’t all need to have our own bank machine. One per neighborhood is sufficient. Think of the home phone as the object instance’s unique direct properties, and the bank machine as a property of the constructor.prototype.

One method in memory to serve all instances is by far more efficient that every instance having their own copy of the method. Using the prototype approach to isolate all the shared methods is also very dynamic in nature.

Consider the following:

function Person(name,age){
    this.name = name;
    this.age = age;
    this.method = function(){
        this.id = this.name;
        console.log(this);
    };
}
var bob = new Person("Bob", 29);
var mary = new Person("Mary", 30);
Person.prototype.method = function(){
    console.log("Object:", this);    
};
var ed = new Person("Edward", 27);
bob.method();
mary.method();
ed.method();

Output:

{ name: 'Bob', age: 29, method: [Function], id: 'Bob' }
{ name: 'Mary', age: 30, method: [Function], id: 'Mary' }
{ name: 'Edward', age: 27, method: [Function], id: 'Edward' }

Notice that none of the objects inherit the prototype of method? They are hard wired, each with their own unique copy of the method included in their own prototype. Remove the method from the constructor and the single prototype is inherited by all.

function Person(name,age){
    this.name = name;
    this.age = age;
}
var bob = new Person("Bob", 29);
var mary = new Person("Mary", 30);
Person.prototype.method = function(){
    this.id = this.name;
    console.log("Object:", this);    
};
var ed = new Person("Edward", 27);
bob.method();
mary.method();
ed.method();

Output:

Object: { name: 'Bob', age: 29, id: 'Bob' }
Object: { name: 'Mary', age: 30, id: 'Mary' }
Object: { name: 'Edward', age: 27, id: 'Edward' }
points
Submitted by Roy
about 9 years

7 comments

reaper almost 9 years

So does that mean an object constructor creates a function for each object whereas the prototype is only one prototype accessed by all the functions and in essence making the code more efficient (especially for real and long programs)? Thanks for such a detailed example and explanation. Much appreciated!

Roy almost 9 years

That’s pretty much it. One method to serve all instances of the object constructor, and only one copy in memory.

M. K. Caruso over 8 years

I also had this question! Thank you @Roy for the thoughtful answer.

Roman Grinyov over 8 years

Why is not implemented for a constructor?

Roman Grinyov over 8 years

I mean the one copy in memory?

Roy over 8 years

The constructor is the pattern for constructing an object instance. There is only one copy.

Roman Grinyov over 8 years

“One method to serve all instances of the object constructor, and only one copy in memory” — it is when we are using the prototype. Why it is not implemented for the constructor? After all, in any case (prototype or initial method), the method is available to all the object instances? Something I was stuck on prototypes. Probably, I should go ahead to understand it …

Answer 54f029c386f552d49500122e

6 votes

Permalink

So probably a really dumb question, but why would we use prototype instead of just adding the function into the object constructor?

points
Submitted by Viggie
about 9 years

Answer 549e6e16937676050800ee01

4 votes

Permalink

This will come up later, so don’t let it confuse you now. I aim to show that a property with undefined value in the constructor.prototype is not an Own Property in an instance until it is set.

We had two object instances in the previous examples, o and ob, with the latter having the name or age properties still undefined. Using a method inherited from Object.prototype, we can query the state of property ownership:

 > ob.hasOwnProperty('name')
=> false
 > o.hasOwnProperty('name')
=> true

Notice that once the name is set, the property becomes owned by the instance, but when it is not set, it is still an inherited property? Something else to investigate in your travels.

points
Submitted by Roy
over 9 years

Answer 549e676251b887d78700ee3e

3 votes

Permalink

JavaScript as a whole is prototypal, meaning the language is modeled upon prototypes. There is no separation of prototype from JavaScript object instances. They all have a prototype.

The top of the prototype chain is null, and the first link in the chain is Object, which has a prototype, Object.prototype that all other object instances inherit from. null is also an object, but a trivial one, and being the top of the chain, is not a link on any chain:

// no inheritance 

 > null.__proto__
TypeError: Cannot read property '__proto__' of null

// no prototype:

 >  null.prototype
TypeError: Cannot read property 'prototype' of null

Moving down to the first link, Object

 > Object.__proto__
=> [Function: Empty]
 > Object.prototype
=> {}

Object inherits the value Function, and its prototype is an empty object. Every object stems from this link, and inherits its properties and methods from the prototype.

Defining a new object is as simple as writing, {} (anonymous) and then assigning it to a reference pointer (variable), var obj = {}; To make an object constructor, we can write it as a function, function Obj(){}, and now we can create new instances of this object, var o = new Obj();

This is where we may find a “purpose” for prototype… namely adding properties to the constructor.prototype that will be inherited by its instances.

function Obj(){}
o = new Obj();

Obj.prototype.name = undefined;
Obj.prototype.setName = function(name){
    this.name = name;
};
Obj.prototype.age = undefined;
Obj.prototype.setAge = function(age){
    this.age = age;
};
console.log(o); // {}
o.setName("Oh");
o.setAge(0);
console.log(o); // { name: 'Oh', age: 0 }

This line might throw one off, but don’t let it.

Obj.prototype.name = undefined;

It’s the same as declaring a variable without defining it. The variable exists (so is a valid reference) but has no defined value.

 > ob = new Obj()
=> {}
 > ob.name
 > ob.age

Notice that no ReferenceError is thrown (but nothing is returned, either)? The new object instance has both properties, just not set. It will still log as an empty object, but if we enumerate it, we see the properties do exist, as well as the inherited methods:

for (var key in ob){
    console.log(key);
}
/* output below
name
setName
age
setAge
*/

We’ve only scratched the surface, so please don’t consider this exhaustive, or even close to fully answering your question. It’s just a start. I’ll leave you to your reading to learn more.

points
Submitted by Roy
over 9 years

2 comments

Roy over 9 years

Challenge what is written here. It needs bearing out.

Peter Kenward about 9 years

Thanks, this is helpful.

Answer 549e7a17e39efe23c200f97b

3 votes

Permalink

Consider the following constructor function:

function myObj(name,age){
    this.name = name;
    this.age = age;
}

Now Run and at the console command line prompt >

 > a = new myObj();
=> { name: undefined, age: undefined }
 > a.hasOwnProperty('name')
=> true

By making name and age defined parameters of the myObj constructor function, we make them Own Properties of all instances, whether set or not. Personally, I would favor the former, to this, because it gives us a way to detect unset properties in object instances, at any point along the way.

// utility function in global scope
var changeName = function(obj, name){
    if (confirm("Change "+ obj.name +" to "+ name +"?")){
        obj.name = name;
    }
};

function myObj(){}
myObj.prototype.name = undefined;
myObj.prototype.setName = function(name){
    if (this.hasOwnProperty('name')){
        changeName(this, name);
    } else {
        this.name = name;
    }
};

var a = new myObj();
a.setName("Aaron"); // set immediately
console.log(a.name); // Aaron
a.setName('Andy'); // needs a confirm or cancel
console.log(a.name); // Aaron or Andy, depending

Just for the record, good, better, best does not enter into this discussion. We are merely exploring different ways to construct a prototype so we can put together functional JavaScript objects that suit their purpose in our programs.

points
Submitted by Roy
over 9 years

3 comments

Mark Cross over 9 years

That was a very clear and concise way to address my question and I appreciate the time you took to answer it so thoroughly. I have a MUCH better understanding of not only prototype and inheritance but also of the hasOwnProperty method and how it all ties together. I’ve read several things recently that made those topics as clear as mud and I appreciate your clarity as I slowly crawl forward with JS and PHP. Thanks again Roy; you’re officially on the Christmas card list!

Roy over 9 years

I feel so much better now, knowing that you actually got something from this. You can’t know how hard it is to tell sometimes if one’s labors are worthwhile, or not. Thank you for letting me know. And, you are welcome!

Peter Kenward about 9 years

Thanks again Roy. I’ve spent some time on your examples and it’s brought me to a much better understanding.

Answer 54f05716e39efeb776001906

0 votes

Permalink

And just for good measure to really expand your mind,

for (var key in Person.prototype){
    console.log(key, Person.prototype[key]);
}

Output

method function (){
    this.id = this.name;
    console.log("Object:", this);    
}
points
Submitted by Roy
about 9 years

3 comments

Roy about 9 years

This shows that the prototype of a constructor is also an object with properties, namely the defined methods and attributes we assign.

Roy about 9 years

this.id = this.name; Ignore. A line that makes no sense that I threw in to demonstrate dynamic updating. Another discussion…

Answer 55677ad1e39efe01e00004b6

0 votes

Permalink

The others have answered this well. I would only add that, according to the “Introduction to Objects II (14/30)” lesson, prototyping is a way to teach an old dog new tricks. :)

points
Submitted by wkisting
almost 9 years

Answer 55cf7a07937676417b0005d1

0 votes

Permalink

Great explanation Roy, I would not have understood this as well if not for your comments….

I took a brief course in C++, a long time ago, and I remember pointers. Could you also think of the object’s prototype as just a pointer to an object, in this case the Person object?

points
Submitted by __zug__
over 8 years

Answer 55cfa87d93767689d200077a

0 votes

Permalink

Could you also think of the object’s prototype as just a pointer to an object, in this case the Person object?

A pointer, yes, that always points UP the prototype chain. JavaScript will crawl up the chain until it finds the reference it is looking for. If none is found, it crashes into null (my verbs). The pointer sees the lowest link that is above it, usually the constructor.prototype.

Consider another type of pointer, a reference to a function:

function foo(){} 
var f = foo; 
console.log(f());// undefined. 

f in this instance is a pointer. We can see the parallel between this and prototype.

Hopefully you won’t let my glibness throw you off the scent of a better understanding. My memory wanders a lot so I tend to describe things in different ways every time. Keep up your study and review of this concept, as my answers are not definitive, and quite often not that accurate, sorry to say. I tend to theorize more than is healthy, one thinks.

points
Submitted by Roy
over 8 years