Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am confused with the following prototype behavior in javascript.

function A(){
};

A.prototype.toString = function(){
            console.log('first');
               }

var a = new A(), b;

A.prototype = {
    toString:function(){
        console.log('second');
    }
}

b = new A();

a.toString();
//outputs :  first

b.toString();
//outputs :  second

Why does a.toString still prints "frist" when compared to b.toString which prints "second". can anyone please explain what i am missing here.

share|improve this question
    
a is created before manipulation of the object and b is after –  Ankit Jun 18 '13 at 21:51
    
Why var a = new A(), b? –  elclanrs Jun 18 '13 at 21:58
1  
@elclanrs why not? –  basilikum Jun 18 '13 at 22:02
    
@basilikum: Oh I misinterpreted, he's just declaring b as var. It's all good. –  elclanrs Jun 18 '13 at 22:05

3 Answers 3

up vote 2 down vote accepted

The prototype link has nothing to do with the constructor that constructed the object, it is stored on objects themselves.

When you call new A() this happens:

var a = {};
a.__proto__ = A.prototype;
A.call(a);

Note that the above is not standard syntax but does work in chrome and firefox.

So when you overwrite A.prototype, a.__proto__ is still linking to the old A.prototype as you would expect with similar code:

var A = 10, a, b;

a = A;
A = 7; //a is still 10
b = A; 

I don't recommend reassigning the prototype, because then you need to re-establish the constructor property and it requires additional level of indentation.

If you want to type less, just store reference to the prototype:

function A() {

}
var fn = A.prototype;

fn.toString = function() {

};

fn.valueOf = function() {

};

fn.toJSON = function() {

};
share|improve this answer
    
I wouldn't say "nothing", rather an object's [[Prototype]] is set to the constructor's prototype at the time the object was constructed. –  RobG Jun 18 '13 at 22:13
    
@RobG that's just basically saying the same thing :P. I am just trying to dispel the belief that the constructor is out there watching all the created instances or something. –  Esailija Jun 18 '13 at 22:19
    
Yes, same thing but different. :-) –  RobG Jun 19 '13 at 3:07

function A(){ };

A.prototype.toString = function(){
            console.log('first');
               }     // here A prints 'first'

var a = new A(), b;  

A.prototype = {    
    toString:function(){
        console.log('second');
    }
}                    // here A prints 'second'

b = new A();

a.toString();
//outputs :  first

b.toString();
//outputs :  second
share|improve this answer
    
this is just the question code copypasted –  Esailija Jun 18 '13 at 21:52
    
trying to show where the A changes it's behavior... –  AntouanK Jun 18 '13 at 21:53

An object's internal [[Prototype]] (the one it inherits from) is set to its constructor's prototype at the time it is constructed. Assigning a new object to the constructor's prototype does not alter the [[Prototype]] of instances that have already been created.

In fact, once an object is created, you can't assign a different [[Prototype]] other than by the non–standard __proto__ property.

Edit

Just to make it really clear:

// A simple constructor
function Person(name) {
  this.name = name;
}

// Assign a method to its default prototype
Person.prototype.showName = function() {
  return this.name;
}

// This instance will be assigned the above as its [[Prototype]]
// with its showName method
var fred = new Person('Fred');

// Assign a new object to Person.prototype 
Person.prototype = {};

// Assign a new showName method
Person.prototype.showName = function() {
  return 'My name is ' + this.name;
}

// This instance has the new object as its [[Prototype]]
var sue = new Person('Sue');

console.log(
    fred.showName() + '\n'  // Fred 
  + sue.showName()          // My name is Sue
);

It can be seen that fred still inherits from the original prototype object, sue inherits from the new object because it was created (instantiated) after the change.

share|improve this answer
    
How come this works obj = {foo:{a:1}, b:1}; function Class(){}; Class.prototype = obj; y = new Class(); y.foo.a = 2; // prints 2 x = new Class(); x.foo.a // prints 2 –  rajn Jun 18 '13 at 22:56
    
Because both x and y are created as instances of Class when it has the same object (obj) as its prototype, so x and y have the same [[Prototype]] (i.e. obj). If you change Class.prototype before creating x, it will inherit from the new object and will have a different [[Prototype]] to y –  RobG Jun 19 '13 at 3:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.