Reputation: 6939
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:
Not-prototypal person:
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)?
Upvotes: 3
Views: 59
Reputation: 339947
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.
Upvotes: 2