3

I have a question about JS prototyping:

If I have the following constructor:

function Person(name) {
     if (!(this instanceof Person))
         return new Person(name);
     this.name = name;
}
Person.prototype.sayHello = function() {
    console.log("Hello from " + this.name);
}

Here I have a method sayHello bound to the prototype of Person, which is more memory efficient that this:

function Person(name) {
     if (!(this instanceof Person))
         return new Person(name);
     this.name = name;
     this.sayHello = function() {
        console.log("Hello from " + this.name);
     }
}

Just a glimpse:

Prototypal person:

enter image description here

Not-prototypal person:

enter image description here

As you see, the reference to the sayHello Function will be "shared" across all the person created, instead of just creating a new Function for each instantiated person. this will then mutate to point to the correct person whenever it is used inside the sayHello() context when sayHello() is called on that specific person.

Now, another variant:

function Person(name) {
     if (!(this instanceof Person))
         return new Person(name);
     this.name = name;
     this.__proto__.sayHello = function() {
        console.log("Hello from " + this.name);
     }
}

And the output is the same as for Person.prototype.sayHello, meaning that sayHello is shared across different persons.

But is there a difference between this two approaches? I guess no, because:

Person.prototype === bob.__proto__ // true

So really, when one should use the former (Person.prototype.* outside the constructor function) instead of the latter (this.__proto__.* inside the constructor function)?

7
  • probably not the answer, just reference purpose -- Did you check these good questions already? 1: stackoverflow.com/questions/572897/… -- 2: stackoverflow.com/questions/2064731/… Commented Apr 16, 2015 at 11:00
  • 4
    Always! Why would you want to mutate the prototype every time the constructor is called? Even though the method(s) would still be shared, every call to the constructor creates a new version of the method and throws away the old one. Just create the method once and be done with it. Commented Apr 16, 2015 at 11:00
  • @FelixKling That's a good reason, but beside this, there aren't any other differences, right? Commented Apr 16, 2015 at 11:02
  • Not from a structural perspective. But your are still cresting a copy of the same function, and external code could keep a reference to an old copy around. Commented Apr 16, 2015 at 11:04
  • 2
    Ah stupid auto-correct. It supposed to be "creating". Commented Apr 16, 2015 at 13:31

1 Answer 1

2

To expand on Felix's comments.

The version that reads:

this.__proto__.sayHello = function() {
    console.log("Hello from " + this.name);
}

shouldn't be used.

Each and every time that the enclosing constructor is invoked the code above will also be run, creating a new copy of that anonymous function, and overwriting the reference currently held in the prototype.

Any code that happens to hold a reference to the previous instance of that function will continue to point to that old version.

In memory efficiency terms it's very similar to writing this.sayHello = function(...) because none of the instances actually share the same copy of the function. In code efficiency terms it's arguably worse (albeit equivalent to using Person.prototype.sayHello = ...) because every invocation requires an ascent up the prototype chain.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.