JavaScript中的原型是什么?

时间:2009-11-20 03:06:36

标签: javascript class prototype

JavaScript类的原型是什么?换句话说,

之间有什么区别
Example.prototype.method {}

Example.method{}

定义Example类时?

编辑:对于那些感兴趣的人,我在这里找到了一个很好的解释(除了下面的答案),因为类方法和构造函数方法之间存在差异:http://idhana.com/2009/07/13/constructor-vs-class-methods-in-javascript/

编辑2:完整答案! http://blog.anselmbradford.com/2009/04/09/object-oriented-javascript-tip-creating-static-methods-instance-methods/

2 个答案:

答案 0 :(得分:5)

不同之处在于后一个示例中您正在创建一个静态方法,如果Example是构造函数,则不会继承该方法。通过在构造函数的prototype属性中定义属性并使用new关键字创建对象,新创建的对象将继承构造函数的原型,从而可以访问这些方法。

一个示例是内置核心构造函数中定义的方法,例如String ..新创建的字符串具有indexOf方法,因为String中定义了一个函数构造函数的原型

typeof String.prototype.indexOf // 'function'

var name = 'John';
alert( name.indexOf('J') ) // 0

下面的代码创建了一个函数构造函数,我们首先定义一个静态方法,创建一个对象,找出该对象没有getName方法,然后我们在原型中定义一个,然后发现该对象确实有一个getName方法

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

重申一下,ECMAScript中的继承主要是通过在函数构造函数的原型中定义属性/方法来实现的,例如,所有核心构造函数,例如Date / Number / String,它们在各自的原型属性中定义了方法,这允许您在使用new关键字创建实例时使用这些方法。

请记住,新创建的对象具有constructor属性,该属性指向构成它的构造函数,我们可以直接访问prototype属性。我们创建的john对象并不直接拥有getName方法,因为解释器无法直接在它向上传递给构造函数的对象上找到它,并在其原型中找到它。

顺便说一下,我们真的不必创建john对象的新实例,正如另一个答案所指出的那样,你可以在创建初始构造函数后在原型中定义属性,并且所有对象都会即使在它们被创建之后也继承了这些原型属性。

静态方法不能依赖上下文,不能依赖于类的特定实例,不能依赖this关键字,因此这不是静态方法:

function Name(name) {
    this.name = name;
    this.getName = function() { return this.name; }
};

这是一个静态方法的例子:

Name.getName = function() {};

但是使getName静态没有任何意义,因为顾名思义它必须依赖于一个对象实例来确定name属性是什么,你应该有更多通用的辅助函数,比如解析函数,如{{ 1}}作为静态方法并在原型中定义实例方法,因为它们比在构造函数中定义Date.parse更有效。

答案 1 :(得分:2)

原型就像一个类定义,但它可以动态更改。每当您实例化某种类型的对象时,它都会使用原型作为模板。

如果更改原型,该类型的对象将进行更改。