JavaScript类的原型是什么?换句话说,
之间有什么区别Example.prototype.method {}
和
Example.method{}
定义Example类时?
编辑:对于那些感兴趣的人,我在这里找到了一个很好的解释(除了下面的答案),因为类方法和构造函数方法之间存在差异:http://idhana.com/2009/07/13/constructor-vs-class-methods-in-javascript/
答案 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)
原型就像一个类定义,但它可以动态更改。每当您实例化某种类型的对象时,它都会使用原型作为模板。
如果更改原型,该类型的对象将进行更改。