我们可以称之为真正的原型继承吗?

发布于 2024-11-04 19:44:14 字数 1195 浏览 0 评论 0原文

我总是对人们试图将某种形式的经典继承强加到 JavaScript 中的方式感到惊讶。我设计了一种方法,可以在某个对象 b 中继承对象 a 的原型方法,而无需将对象 b 的原型方法添加到对象 a,并且可以使用从 1。现在我很好奇:你会说这真的是原型“继承”吗?这是一个可行的方法吗?这其中有陷阱吗?

下面是一些示例代码:

Object.prototype.inheritsFrom = function(obj){
    var prototo   = this.prototype, 
        protofrom = obj.prototype;
    for (var l in protofrom) {
        if (protofrom.hasOwnProperty(l)){
            prototo[l] = protofrom[l];
        }
    }
}

function Obj1(){
    var const1 = 25;
    if (!Obj1.prototype.getConst1){
       Obj1.prototype.getConst1 = function(){
           return const1;
       }
    }
}

function Obj2(){
    var const2 = 50;
    if (!Obj2.prototype.getConst2){
       Obj2.prototype.getConst2 = function(){
           return const2;
       }
    }
    Obj2.inheritsFrom(Obj1);
}

var instanceA = new Obj1,
    instanceB = new Obj2;

现在 instanceA 包含方法 getConst1instanceB 包含方法 getConst1getConst2 code>,正如您在 这个 jsfiddle 中看到的那样。

1 通过在构造函数中分配原型方法,有效地使用由此创建的闭包。

I'm always flabbergasted by the way people try to force some form of classical inheritance into javascript. I have designed a method to inherit in some object b the prototype methods from object a, without adding prototype methods from object b to object a, and the possibility to use private variables from the object inherited from1. Now I'm curious: would you say this is really prototypal 'inheritance'? Is it a viable method? Are there pittfals to it?

Here's some example code:

Object.prototype.inheritsFrom = function(obj){
    var prototo   = this.prototype, 
        protofrom = obj.prototype;
    for (var l in protofrom) {
        if (protofrom.hasOwnProperty(l)){
            prototo[l] = protofrom[l];
        }
    }
}

function Obj1(){
    var const1 = 25;
    if (!Obj1.prototype.getConst1){
       Obj1.prototype.getConst1 = function(){
           return const1;
       }
    }
}

function Obj2(){
    var const2 = 50;
    if (!Obj2.prototype.getConst2){
       Obj2.prototype.getConst2 = function(){
           return const2;
       }
    }
    Obj2.inheritsFrom(Obj1);
}

var instanceA = new Obj1,
    instanceB = new Obj2;

Now instanceA contains method getConst1, instanceB contains methods getConst1 and getConst2, as you can see in this jsfiddle.

1 By assigning the prototype methods in the constructor function, effectively using the closure created by that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡淡の花香 2024-11-11 19:44:14

不,这不是典型的继承。在真正的原型继承中,对原型的更改出现在依赖该原型的对象中。在您的示例中,它们没有,因为它们只是被复制。

我并不是说在某些情况下它可能不是另一种有用的继承形式,但它不是典型的。从某种意义上说,我什至不确定它是继承,尽管我认为人们可以以任何一种方式争论它,但无论如何这并不重要。

下面是添加到原型的示例:

function Parent() {
}
Parent.prototype.foo = function() {
  display("foo!");
};

function Child() {
}
Child.prototype = new Parent();

var c = new Child();

display("[before] typeof c.foo === '" + typeof c.foo + "'");
// shows "[before] typeof c.foo === 'function'"
display("[before] typeof c.bar === '" + typeof c.bar + "'");
// shows "[before] typeof c.bar === 'undefined'"
display("Note that c.bar is currently undefined");

Parent.prototype.bar = function() {
  display("bar!");
};

display("[after] typeof c.bar === '" + typeof c.bar + "'");
// shows "[after] typeof c.bar === 'function'"
display("Now c.bar is a function");

c.foo();
c.bar();

Live copy

请注意,这不是一个晦涩的案例。毕竟,您自己的代码依赖于对 Object.prototype 的更改反映在已从其派生的其他事物(Function)中。


离题强烈建议不要向Object.prototype添加任何内容。它会破坏大量假设在 {} 上使用 for..in 不会产生任何属性的代码。在您能够可靠地将添加标记为不可枚举之前(ECMAScript5 现在提供了一种方法来做到这一点,但大多数实现还没有),请远离 Object.prototype。只是一个推荐。此外,在您的情况下,它没有意义,因为 inheritsFrom 仅适用于 Function 实例,因此您需要将其添加到 Function。代替原型(这样危险性要小得多)。

No, that's not prototypical inheritance. In true prototypical inheritance, changes to the prototype appear in the objects that rely on that prototype. In your example, they don't, because they're only copied.

I'm not saying it may not be another useful form of inheritance for some situations, but it's not prototypical. In some sense I'm not even sure it's inheritance, although I think one could argue it either way and it doesn't really matter regardless.

Here's an example of adding to the prototype:

function Parent() {
}
Parent.prototype.foo = function() {
  display("foo!");
};

function Child() {
}
Child.prototype = new Parent();

var c = new Child();

display("[before] typeof c.foo === '" + typeof c.foo + "'");
// shows "[before] typeof c.foo === 'function'"
display("[before] typeof c.bar === '" + typeof c.bar + "'");
// shows "[before] typeof c.bar === 'undefined'"
display("Note that c.bar is currently undefined");

Parent.prototype.bar = function() {
  display("bar!");
};

display("[after] typeof c.bar === '" + typeof c.bar + "'");
// shows "[after] typeof c.bar === 'function'"
display("Now c.bar is a function");

c.foo();
c.bar();

Live copy

Note that this is not an obscure case. After all, your own code relies on changes to Object.prototype being reflected in the other things (Function) that have already derived from it.


Off-topic: Strongly recommend never adding anything to Object.prototype. It will break a huge amount of code that assumes that using for..in on a {} would yield no properties. Until you can reliably mark additions as non-enumerable (ECMAScript5 now provides a way to do that, but most implementations don't have it yet), just stay away from Object.prototype. Just a recommendation. Additionally, in your case, it doesn't make sense, because the inheritsFrom only works for Function instances, so you'd want to add it to Function.prototype instead (which is a lot less dangerous).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文