为什么我们要用`Boy.prototype = new Human;`来模拟继承?

发布于 2024-11-07 08:39:52 字数 613 浏览 0 评论 0原文

我不明白为什么每个人都使用 Boy.prototype = new Human; 来模拟继承。你看,我们想要的是A的函数吧?我们可以在不实例化一个新的 A 的情况下做到这一点(事实上,实例化一个新的 A 确实会给我们带来不想要的结果,因为我们实际上正在运行实例化函数,这不是我们想要的)

所以这不是一个更好的解决方案吗?

for (var prop_name in Human.prototype) {
Object.defineProperty(
          Boy.prototype,
          prop_name,
          Object.getOwnPropertyDescriptor(Human.prototype,prop_name)
        );
}

假设我们很特别,不仅想要 Human.prototype 中的可枚举属性,我们仍然可以通过使用 Object.getOwnPropertyNames 并在原型链上调用它来实现它,而原型链又可以通过 <代码>Object.getPrototypeOf。

那么,当我们有更好的选择时,使用 Boy.prototype = new Human; 来模拟继承到底有什么好处呢?

i don't get why everyone is using Boy.prototype = new Human; to simulate inheritance. Look, what we want is the function's of A right? we can do that without instantiating a new A (in fact instantiating a new A does give us undesirable results, in the sense that we are actually running the instantiating function which isn't what we want)

So isn't this a better solution?

for (var prop_name in Human.prototype) {
Object.defineProperty(
          Boy.prototype,
          prop_name,
          Object.getOwnPropertyDescriptor(Human.prototype,prop_name)
        );
}

Say we are that particular and want not only the enumerable properties in Human.prototype we could still achieve it by using Object.getOwnPropertyNames and calling it on the prototype chain, which in turn is available to us through Object.getPrototypeOf.

So what exactly is the benefit of doing Boy.prototype = new Human; to simulate inheritance when we have better options available to us?

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

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

发布评论

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

评论(2

万人眼中万个我 2024-11-14 08:39:52

更好的选择是创建一个中间体来保存原型。

function extend(clazz, superclass) {
    var intermediate = function() {};
    intermediate.prototype = superclass.prototype;
    clazz.prototype = new intermediate();
    // Following line is optional, but useful
    clazz.prototype.constructor = clazz;
}

这避免了不必要的复制,但仍然意味着您不需要实例化将在其构造函数中工作的对象。它还设置了原型链,以便您可以使用instanceof。它也不会导致某些继承反模式可能造成的超类原型污染。

为了完整起见,您的子类应该在其构造函数中调用超类构造函数,您可以使用 Superclass.call(this); 来执行此操作。

编辑:从 ES5 开始,您可以替换对 extend 的调用,它

Subclass.prototype = Object.create(Superclass.prototype);

可以执行相同的操作。

A better option is to create an intermediate to hold the prototype.

function extend(clazz, superclass) {
    var intermediate = function() {};
    intermediate.prototype = superclass.prototype;
    clazz.prototype = new intermediate();
    // Following line is optional, but useful
    clazz.prototype.constructor = clazz;
}

This avoids unnecessary copying, but still means that you don't need to instantiate an object that will do work in its constructor. It also sets up the prototype chain so that you can use instanceof. It also doesn't result in superclass prototype contamination which some inheritance antipatterns can.

For completeness, your subclass should call the superclass constructor in its constructor, which you can do with Superclass.call(this);.

EDIT: Since ES5, you can replace calls to extend with

Subclass.prototype = Object.create(Superclass.prototype);

which does the same thing.

我们的影子 2024-11-14 08:39:52
  • 它正确设置了原型链,这意味着 instanceofisPrototypeOf() 会起作用
  • 它不太冗长

有一些简单但丑陋的解决方法可以防止构造函数在您刚刚使用时执行其通常的初始化它创建一个原型对象。例如,您可以检查参数:

function Boy(name) {
    if (arguments.length == 1) {
        this.name = name;
        // Do other initialization
    }
}

...或者将初始化移动到必须显式调用的单独方法中:

function Boy(name) {}

Boy.prototype.init = function(name) {
    this.name = name;
    // Do other initialization
}

这有一个明显的缺点,即要求您记住调用 init()每当你创建一个新的Boy时。

在 ECMAScript 5 环境中(例如,大多数浏览器的当前版本),更好的选择可能是 ECMAScript 5 的 Object.create(),它允许您创建一个直接从另一个对象继承的对象,并为您设置原型链。这可以被模拟(但只是近似:参见ES5中的Object.defineProperty? ) 在非 ES5 环境中:

if (!Object.create) {
    Object.create = function(o) {
        function F() {}
        F.prototype = o;
        return new F();
    }; 
}
  • It sets up the prototype chain correctly, meaning that instanceof and isPrototypeOf() will work
  • It's less verbose

There are simple but ugly workarounds to prevent a constructor function from performing its usual initialization when you're just using it to create a prototype object. For example, you could either check the arguments:

function Boy(name) {
    if (arguments.length == 1) {
        this.name = name;
        // Do other initialization
    }
}

... or move the initialization into a separate method that has to be called explicitly:

function Boy(name) {}

Boy.prototype.init = function(name) {
    this.name = name;
    // Do other initialization
}

This has the obvious downside of requiring you to remember to call init() whenever you create a new Boy.

In ECMAScript 5 environments (current versions of most browsers, for example), a better option may be ECMAScript 5's Object.create(), which allows you to create an object which inherits directly from another object and sets up the prototype chain for you. This can be emulated (but only approximately: see Object.defineProperty in ES5?) in non-ES5 environments:

if (!Object.create) {
    Object.create = function(o) {
        function F() {}
        F.prototype = o;
        return new F();
    }; 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文