0

I have the following piece of code:

var Test = function () {
};
Test.prototype.doSomething = function() {
  return "done";
};

Now, I create an object of Test

var t = new Test();
alert(t.doSomething());    // Correct alerts "done"

Now I add another method to the prototype:

Test.prototype.fly = function() { return "fly"; };
alert(t.fly());       // Correctly alerts "fly" (existing objects get "live udpated")

Now, I make the prototype point to a blank object:

Test.prototype = {};
alert(t.doSomething());    // Continues to alert "done", but why?
alert(t.fly());            // Continues to alert "fly", but why?

var t2 = new Test();
alert(t.doSomething());    // As expected, this does not work
  1. When I add a method to prototype, it reflects correctly on all new and existing objects

  2. When I "blank" out the prototype by doing <name>.prototype = {};, it only "blanks" out new instances, but not existing ones. Why?

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
Taha Ahmad
  • 559
  • 4
  • 16
  • possible duplicate of [How does JavaScript .prototype work?](http://stackoverflow.com/questions/572897/how-does-javascript-prototype-work) – raina77ow Dec 27 '13 at 13:41
  • @raina77ow I think this question is little different. – thefourtheye Dec 27 '13 at 13:42
  • @thefourtheye Of course, because it's a subset of the questions answered in that thread. – raina77ow Dec 27 '13 at 13:42
  • 2
    Objects keep their own reference copy to their `prototype` object (via [`[[Prototype]]`](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6.2)). Augmenting that object from the constructor's `prototype` property will be reflected in existing instances, but replacing it won't (since that only affects 1 copy). And, once ES6 is standard, you'll be able to set the instance's copy using [`Object.setPrototypeOf()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf). – Jonathan Lonowski Dec 27 '13 at 13:43

3 Answers3

4

An analogy is this:

var a = {foo : 'bar'};
var b = a; //the same object as a
var c = a;
var d = a;

a.apple = 'orange';

a = 1;  //a === 1. b, c and d stay the same, pointing to the object with apple

What I did here is replace what a was pointing, but not the object itself.

When you added fly, you are modifying that single prototype object which all instances share, the object that Test.prototype is currently pointing to.

But when you assigned a blank object to Test.prototype, you modified what Test.prototype was pointing to. It does not modify what the existing instances are pointing to. But from this point on, any new instances will now use the new object on Test.prototype as their prototype object.

If you are familiar with C, I'd rather think of JS variables as pointers rather than references.

Joseph
  • 117,725
  • 30
  • 181
  • 234
0

I'm completing the previous answer, if you want reflect your changes on all instances you must update the prototype correctly.

Prototype property is an object and you can delete a propery with the reserved keyword 'delete'.

If you want delete 'doSomething' property :

delete Test.prototype.doSomething;
Payou
  • 371
  • 2
  • 7
0

consider

function Foo(){}
Foo.prototype = {a:{"VMAddress":"@1234"}}

consider that Foo.prototype.a object has VMAddress "@1234" if you create object now then,

var f1 = new Foo();

now f1.a will point to the same object ie with Virtual Machine address "@1234" if you look

f1.a === Foo.prototype.a ;//prints tue

If you change prototype to some other value now,

Foo.prototype = {a:{"VMAddress":"@5678"}}

and if you create object now then,

var f2 = new Foo();

although

f2.a === Foo.prototype.a; //prints true because both point to same VM address @5678

but

f1.a === f2.a; //prints false

why?? because their VM address are different(one is @1234 and other is @5678) and infact they are different object

final verdict the prototype chain at the time of object creation decides what an object's prototype will be.

WebServer
  • 1,316
  • 8
  • 12