在JS中使用原型构造函数

Dex*_*olf 10 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'
Run Code Online (Sandbox Code Playgroud)

chj*_*hjj 11

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

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

在你的代码贴出来,是的,做继承时的方式,有必要重新构造(如果你想在那里),因为你实例化对象来充当孩子的原型有一个constructor属性指向了错误的构造函数(它的构造).

在ES5中,您可以:

Child.prototype = Object.create(Parent.prototype, {
  constructor: { value: Child, enumerable: false }
});
Run Code Online (Sandbox Code Playgroud)

编辑:另外,可能是值得一提的,使用非标准做继承时__proto__,就没有必要重新构造,因为__proto__仅仅规定和对象的原型,它说哪,在其中,当自己的财产没有按"查找将要执行的对象存在.一个新的prototype将永远有一个叫做的属性constructor.

这样做:

var child = function() {};
child.prototype.__proto__ = parent.prototype;
Run Code Online (Sandbox Code Playgroud)

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

  • Raynos,不,我不确定IE6,因为我并不真正关心IE6.另外,Object.create没有为你设置构造函数,它没有构造函数的概念,事实上,这就是Object.create的要点.您只能获得与父构造函数相等的构造函数属性,这对于继承来说是错误的.所以你需要改变它. (4认同)
  • 你确定IE6不检查`constructor`属性吗?并且`Object.create`为你设置`constructor`属性.你不必手动完成它 (2认同)

Dom*_*nic 5

如果你更换线

Me.prototype.constructor = Me; // Why?
Run Code Online (Sandbox Code Playgroud)

console.log(Me.prototype.constructor);
Me.prototype.constructor = Me; // Why?
Run Code Online (Sandbox Code Playgroud)

你会发现在设置它之前,Me.prototype.constructorYou因为这Me.prototype是一个You由于线路的实例

Me.prototype = new You();
Run Code Online (Sandbox Code Playgroud)

所以,// Why?评论这一行是必要的,以"修复"这种错误的印象,即你通过这种方式进行继承而给出了JavaScript.


本质上问题是因为您尝试使用原型继承来实现经典继承.原型继承工作的对象实例,并没有"阶级",甚至,真的,概念"类型",但JavaScript的让事情额外的混乱与整个new,.constructorinstanceof业务.

做这种事情的一种更原型的方法是避免构造函数支持幂构造函数,即返回具有所需形式的对象的函数:

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"
Run Code Online (Sandbox Code Playgroud)

这里我们用Object.create来说"基于这个其他对象实例创建一个对象实例".另一个实例是一个新的空对象,begetPart以及一个预先填充了一些属性的新"部分实例" begetTire.

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