What is the differences between:
function Gandalf() {
this.color = 'grey';
}
Gandalf.prototypeeBack = function() {
this.color = 'white';
}
And:
function Gandalf() {
this.color = 'grey';
thiseBack = function() {
this.color = 'white';
return this;
};
}
And under which circumstances should I hook the method onto the prototype, or not?
What is the differences between:
function Gandalf() {
this.color = 'grey';
}
Gandalf.prototype.eBack = function() {
this.color = 'white';
}
And:
function Gandalf() {
this.color = 'grey';
this.eBack = function() {
this.color = 'white';
return this;
};
}
And under which circumstances should I hook the method onto the prototype, or not?
Share edited Jun 28, 2013 at 10:51 Felix Kling 818k181 gold badges1.1k silver badges1.2k bronze badges asked Jun 28, 2013 at 10:00 gskleegsklee 4,9444 gold badges41 silver badges56 bronze badges 3- 4 depends on how many Galdalfs you've got. – georg Commented Jun 28, 2013 at 10:03
- possible duplicate of Use of 'prototype' vs. 'this' in Javascript? – Felix Kling Commented Jun 28, 2013 at 10:50
- 1 @thg435 Depends on how many Galdalfs you've got? You just ruined a great ment because of a typo. – Aadit M Shah Commented Jun 29, 2013 at 15:45
3 Answers
Reset to default 6Alright Agent Kay, I'll approach this question in a different way than Esailija did. Let's begin with simple objects. For example say you already have an object called gandalf
:
var gandalf = {
color: "grey",
eBack: function () {
this.color = "white";
return this;
}
};
There are no constructors in this code. Hence this code is easy to understand. Am I right or am I right?
Alright, now I'm going to do something awesome. I'll create radagast
from gandalf
:
var radagast = Object.create(gandalf);
radagast.color = "brown";
What's happening here? Let's break it up:
- We create a new object called
radagast
fromgandalf
usingObject.create
. Henceradagast
inherits fromgandalf
. - We set the
color
ofradagast
to brown instead of grey.
To make it even more simple imagine you and I had the following conversation:
I: Hey Agent Kay, I met Radagast yesterday.
U: Who's Radagast?
I: Hmm... do you know who's Gandalf?
U: Yes, I do.
I: Well Radagast is just like Gandalf except that he's brown instead of white.
This is exactly how inheritance works in JavaScript. You see JavaScript has prototypal inheritance. In prototypal inheritance objects inherits from other objects. In this case radagast
inherited from gandalf
.
Now they way prototypal inheritance is usually implemented in JavaScript is weird. I call it the constructor pattern of prototypal inheritance. For example, take your code:
function Gandalf() {
this.color = "grey";
}
Gandalf.prototype.eBack = function() {
this.color = "white";
return this;
};
Now when you create an instance of Gandalf
what object does the instance inherit from? It inherits from Gandalf.prototype
:
var gandalf = new Gandalf;
alert(Object.getPrototypeOf(gandalf) === Gandalf.prototype); // true
What's happening when you say new Gandalf
is:
var gandalf = Object.create(Gandalf.prototype);
Gandalf.call(gandalf);
If you expand Gandalf.call(gandalf)
the you get:
var gandalf = Object.create(Gandalf.prototype);
gandalf.color = "grey";
Now take your second example:
function Gandalf() {
this.color = "grey";
this.eBack = function() {
this.color = "white";
return this;
};
}
In this case when you create an instance of Gandalf
you're essentially doing this:
var gandalf = Object.create(Gandalf.prototype);
gandalf.color = "grey";
gandalf.eBack = function () {
this.color = "white";
return this;
};
Hence every time you create a new Gandalf
you create a new function eBack
. Thus if you call new Gandalf
10 times you'll have 10 different eBack
functions as well.
Compared to this in the first example since eBack
is defined on Gandalf.prototype
, every time we call new Gandalf
we get a new object which inherits from Gandalf.prototype
. Hence there's only one eBack
function which is shared amongst all instances of Gandalf
. Isn't that better?
Essentially think of your first example like this:
var gandalfPrototype = {
create: function () {
var gandalf = Object.create(this);
gandalf.color = "grey";
return gandalf;
},
eBack: function () {
this.color = "white";
return this;
}
};
var gandalf = gandalfPrototype.create(); // there's only one eBack function
Similarly your second example is equivalent to this:
var gandalfPrototype = {
create: function () {
var gandalf = Object.create(this);
gandalf.color = "grey";
gandalf.eBack = function () {
this.color = "white";
return this;
};
return gandalf;
}
};
var gandalf = gandalfPrototype.create(); // there's 1 eBack for each instance
Remember that when you use new
before a function call you're actually inheriting from the prototype
of the function. Not the function itself.
Finally I would like to say (because I'm a big fan of J.R.R. Tolkien) that this is the way I would write your code:
var wizard = {
create: function (color) {
var wizard = Object.create(this);
wizard.color = color;
return wizard;
}
};
var gandalf = wizard.create("grey");
gandalf.eBack = function () {
this.color = "white";
return this;
};
var saruman = wizard.create("white");
var radagast = wizard.create("brown");
Thank you for reading my answer.
The reason to put it on prototype is because every object created can use the same function object (functions are merely callable objects), they only need different identity and data. But in the second case you are creating unique function objects for each object even though they can use the same function object.
Since you seem to know PHP, the difference would be similar in PHP:
class Gandalf {
public $color = "grey";
public function eBack() {
$this->color = "white";
}
}
class Gandalf {
public $color = "grey";
//Create the method inside constructor everytime
public function __construct() {
$this->eBack = function() {
$this->color = "white";
return $this;
}->bindTo($this, $this);
}
}
It is hard to say when to use the other when performance is not a concern. Personally the obfuscation of the constructor function and the additional indentation level are enough for me to prefer the prototype.
To answer:
under which circumstances should I hook the method onto the prototype, or not?
If you have a function that need to access private vars
of an object created with a constructor function, it needs to be inside constructor function.
function Gandalf() {
var age = '30000'; //approximate
this.alertAge1 = function() {
alert( age );
};
}
Gandalf.prototype.alertAge2 = function() {
// age not visible from here
};
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745069264a4609446.html
评论列表(0条)