在JS中使用原型构造函数

时间:2011-07-30 17:35:59

标签: javascript oop

有人可以向我解释Me.prototype.constructor = Me;的用法吗?为什么需要这个代码工作时没有呢?

在代码中,在Me对象上创建对象并将其实例化并替换旧的原型对象。为什么我需要在给定代码中指向Me构造函数?

function Me(){
    this.name = 'Dejan';

}

function You(){
    this.name = 'Ivan';
}

Me.prototype = new You();

somebody = new Me();

Me.prototype.constructor = Me; // Why?

Me.prototype.foo = function(){
    alert('Proto Me!'); // It always fire up this alert, ether constructor is pointing to Me or not... !
}

You.prototype.foo = function(){
    alert('Proto You!');
}

somebody.foo();
alert(somebody.name); // Alert 'Dejan'

2 个答案:

答案 0 :(得分:11)

它不是必需的,并且instanceof甚至不需要与普遍看法相反(instanceof内部检查原型链并且不需要构造函数属性)。通常,constructor本质上是构造函数prototype上的非可枚举属性。因此,给予由该构造函数实例化的任何对象,一个不可枚举的constructor属性,指向该构造函数。

如果你需要,最好把它放在那里,理想情况下是不可枚举的。有些代码会假设对象上存在.constructor

在你发布的代码中,是的,当以这种方式进行继承时,有必要重置构造函数(如果你想在那里),因为你实例化作为子原型的对象有一个指向错误构造函数的构造函数属性(它的构造函数)。

在ES5中,你会这样做:

Child.prototype = Object.create(Parent.prototype, {
  constructor: { value: Child, enumerable: false }
});

编辑:另外,值得一提的是,在使用非标准__proto__进行继承时,没有必要重置构造函数,因为__proto__只是指定和对象的原型,也就是说,当自己的属性不存在时将执行查找的对象。新的prototype将始终具有名为constructor的属性。

这样做:

var child = function() {};
child.prototype.__proto__ = parent.prototype;

您不必设置构造函数,因为child.prototype的基本构造函数属性仍然存在。如果被访问,则不需要执行原型链查找。

答案 1 :(得分:5)

如果替换

Me.prototype.constructor = Me; // Why?

console.log(Me.prototype.constructor);
Me.prototype.constructor = Me; // Why?

在设置之前,您会发现Me.prototype.constructorYou,因为Me.prototypeYou的实例,因为该行

Me.prototype = new You();

所以,带有// Why?注释的行是必要的,以“修复”这种错误的印象,即您通过这种方式进行继承来提供JavaScript。


基本上问题来自于您尝试使用原型继承来实现经典继承。原型继承适用于对象实例,没有“类”的概念,甚至没有“真正的”类型“,但JavaScript使整个new.constructor和{{1}更加混乱商业。

做这种事情的更原型的方法是避开构造函数,转而使用幂函数构造函数,即返回具有所需形式的对象的函数:

instanceof

这里我们使用function begetPart(partNumber, description) { return Object.create({}, { number: { value: partNumber }, description: { value: description }, describe: { value: function () { alert(this.description); } } }); } function begetTire(partNumber, speed) { return Object.create( begetPart(partNumber, "A tire"), { speed: { value: speed }, describe: { value: function () { alert(this.description + "; speed = " + this.speed); } } } ); } var genericPart = begetPart(1234, "A widget"); genericPart.describe(); // alerts "A widget" var tire = begetTire(4567, "fast"); tire.describe(); // alerts "A tire; speed = fast" 来说“基于这个其他对象实例创建一个对象实例”。另一个实例是Object.create的新空对象和新的“部分实例”,其中一些属性已预先填充begetPart

这更好地反映了JavaScript和原型继承实际上是如何工作的,因为在原型继承中,对象实例继承自其他对象实例,而没有整个“类型”或“类”的想法妨碍。