What are prototypes in JavaScript?
What is a prototype for a JavaScript class? In other words, what is the difference between
Example.prototype.method {}
and
Example.method{}
when defining the Example class?
Edit: For those interested, I found a great explanation (in addition to the answer below) here for the difference between class methods and constructor methods: http://idhana.com/2009/07/13/constructor-vs-class-methods-in-javascript/
Edit 2: The full answer! http://blog.anselmbradford.com/2009/04/09/object-开发者_Go百科oriented-javascript-tip-creating-static-methods-instance-methods/
The difference is in the latter example you're creating a static method, which is not inherited if Example
is a constructor function. By defining properties in the prototype
property of a constructor function and creating objects with the new
keyword, the newly created objects inherit the prototype of the constructor and thus have access to those methods.
An example would be the methods defined in the built-in core constructors, such as String
.. newly created strings have a indexOf
method because there was one defined in the String
function constructor's prototype
typeof String.prototype.indexOf // 'function'
var name = 'John';
alert( name.indexOf('J') ) // 0
The code below creates a function constructor, we first define a static method, create an object, find out the object does not have a getName method, then we define one in the prototype and find that now the object does have a getName method.
function Name(name) {
this.name = name;
};
Name.getName = function(){};
var john = new Name();
typeof john.getName // undefined
var john = new Name();
Name.prototype.getName = function(){ alert( this.name )};
typeof john.getName
john.constructor.prototype.getName == john.getName // true
So to reiterate, inheritance in ECMAScript is achieved primarily by defining properties/methods in the prototype of a function constructor, example would be all the core constructors such as Date/Number/String which have methods defined in their respective prototype properties, which allows you to use those methods when you create an instance with the new
keyword.
Remember that the newly created object has a constructor
property which points to the constructor which made it, and we can access the prototype
property directly. The john
object we created does not directly own the getName
method, since the interpreter cannot find it directly on the object it travels upwards to the constructor and finds it in its prototype.
And btw, we didn't really have to create a new instance of the john
object, as pointed in the other answer you can define properties in the prototype after you create the initial constructor, and all objects would inherit those prototypal properties even after they've been created.
A static method cannot rely on context, can't rely on a specific instance of a class, can't rely on the this
keyword therefore this would not be a static method:
function Name(name) {
this.name = name;
this.getName = function() { return this.name; }
};
This would be an example of a static method:
Name.getName = function() {};
but there's absolutely no sense in making getName
static because as the name implies it must rely on an object instance to determine what the name property is, you should have more generic helper functions like parsing functions such as Date.parse
as static methods and define instance methods in the prototype as they're more efficient than defining this.foo = function(){}
in the constructor.
A prototype is like a Class definition, but it can be changed dynamically. Whenever you instantiate an object of a certain type, it uses the prototype as the template.
If you change a prototype, objects of that type will have those changes.
精彩评论