سؤال

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.

هل كانت مفيدة؟

المحلول

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() {

};

نصائح أخرى

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

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top