我应该在JavaScript中连接到子原型属性 [英] What should I connect to the child prototype property in JavaScript

查看:74
本文介绍了我应该在JavaScript中连接到子原型属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,我真的不知道如何更详细地说明问题。在这个例子中可以看到最常见的继承方式:

I'm sorry, but I really don't know how to specify more exactly the question. The most common way of inheritance can be seen in this example:

function Shape() {
  this.x = 0;
  this.y = 0;
}

//superclass method
Shape.prototype.move = function(x, y) {
    this.x += x;
    this.y += y;
    console.info("Shape moved.");
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); //call super constructor.
}

//subclass extends superclass
Rectangle.prototype = new Shape();

var rect = new Rectangle();

rect.move(2, 1);

我担心以下代码:

//subclass extends superclass
Rectangle.prototype = new Shape();

直接连接到父原型属性是不是更好。

Isn't it better to connect directly to the parent prototype property.

Rectangle.prototype = Shape.prototype;

据我所知,所有对象都直接从Object继承。他们的原型不是连接到Object的某个实例而是连接到它的原型属性?

As much as I understand this is the case with all objects inheriting directly from Object. Their prototype is connected not to some instance of Object but to its prototype property?

在上面的例子中,Shape.call(this);将复制属性(或类似的东西),我们只需要继承Shape.prototype中的那些方法。或者可能是我遗失了什么?

In the above case Shape.call(this); will copy the properties(or something like this) and we need to inherit only methods which are so and so in the Shape.prototype. Or may be I am missing something?

推荐答案


我担心以下代码:

I am concerned about the following code piece:

//subclass extends superclass
Rectangle.prototype = new Shape();


你应该是,这是一种常见模式,但不是很常见好的,因为那时你正在使用 Shape 两者创建原型来初始化实例。它应该做一个或另一个。 (例如,考虑一下,如果需要提供 Shape 参数,你会做什么?你会使用什么args创建 Rectangle.prototype ?)

You should be, that's a common pattern, but not a very good one, because then you're using Shape both to create prototypes and to initialize instances. It should do one or the other. (Consider, for instance, what you'd do if you needed to give Shape arguments? What args would you use creating the Rectangle.prototype?)

但你不想要 Rectangle.prototype = Shape.prototype ,因为那时你不能把东西添加到 Rectangle.prototype (因为它指向同一个对象 Shape.prototype 是指着,你也可以将它们添加到 Shape 实例中。

But you don't want Rectangle.prototype = Shape.prototype either, because then you can't add things to Rectangle.prototype (since it's pointing at the same object Shape.prototype is pointing at, you'd add them to Shape instances as well).

所以我们想要的是创建使用 Shape.prototype 作为其原型的新对象(例如,继承自 Shape.prototype )就像通过 new Shape 创建的对象,但是没有调用 Shape 来创建它;然后将该新对象用作 Rectangle.prototype

So what we want is to create a new object that uses Shape.prototype as its prototype (e.g., that inherits from Shape.prototype) just like the objects created via new Shape do, but without calling Shape to create it; and then use that new object as Rectangle.prototype.

从ECMAScript5开始,我们可以使用 Object.create

As of ECMAScript5, we can do that using Object.create:

Rectangle.prototype = Object.create(Shape.prototype);

Object.create 创建一个新对象将你给它的第一个参数指定为对象的底层原型。

Object.create creates a new object and assigns the first argument you give it as the object's underlying prototype.

完成后,虽然它不是严格必要,我们也应该设置新对象上的构造函数属性,以便它引用 Rectangle

Having done that, although it's not strictly necessary, we should also set the constructor property on our new object so that it refers to Rectangle:

Rectangle.prototype.constructor = Rectangle;

我们这样做是因为这样, Rectangle.prototype Rectangle 看起来像规范的第13.2节说它应该看起来。基本上,如果你有一个构造函数 X ,那么 X.prototype.constructor 应该引用 X 。有时候人们依赖它来进行克隆操作等(JavaScript本身依赖于&mbsp;&mbsp; —例如, instanceof 不依赖于它)。

We do that because that way, the relationship between Rectangle.prototype and Rectangle looks the way §13.2 of the spec says it should look. Basically, if you have a constructor function X, then X.prototype.constructor should refer to X. Sometimes people rely on that for cloning operations and such (JavaScript itself does not rely on that — for instance, instanceof doesn't rely on it).

所以我们可以使用ES5的 Object.create 来做到这一点。但即使在今天,并非所有JavaScript引擎都支持 Object.create 。所以相反,我们可以通过创建一个临时构造函数来间接地做到这一点,让它借用 Shape.prototype 作为其原型属性,然后使用该临时构造函数创建我们的新对象以用作 Rectangle.prototype

So we can use ES5's Object.create to do this. But even today, not all JavaScript engines support Object.create. So instead, we can do this indirectly, by creating a temporary constructor function, letting it borrow Shape.prototype as its prototype property, and then using that temporary constructor to create our new object to use as Rectangle.prototype:

function Ctor() { }
Ctor.prototype = Shape.prototype; // Borrow the prototype
Rectangle.prototype = new Ctor(); // Create the new object

...再次我们应该设置构造函数 property:

...and again we should set the constructor property:

Rectangle.prototype.constructor = Rectangle;

通常情况下,您不是每次都写出所有内容,而是使用这样的帮助:

Typically, rather than writing all that out each time, you use a helper like this:

function derive(Parent, Child) {
    function Ctor() { this.constructor = Child; }
    Ctor.prototype = Parent.prototype;
    Child.prototype = new Ctor();
    return Child; // For chaining
}

然后像这样使用它:

derive(Shape, Rectangle);

所有这一切的最终结果是我们只调用 Shape 来自 Rectangle ,用于初始化实例。我们不会调用它来创建 Rectangle.prototype

The end result of all this is that we only call Shape from within Rectangle, to initialize instances. We don't call it to create Rectangle.prototype.

如果你对JavaScript中的继承管道感兴趣,您可能对我的 Lineage 脚本感兴趣,它处理上述以及更多。当我说感兴趣时,我并不一定意味着使用它(虽然欢迎你),但是看看未经证实的来源和这个页面比较 Lineage 在没有帮助的情况下做同样的事情可以让你知道这些东西是如何工作的。

If you're interested in inheritance plumbing in JavaScript, you might be interested in my Lineage script, which handles the above and a lot more besides. When I say "interested," I don't necessarily mean using it (although you're welcome to), but looking at the unminified source and at this page comparing Lineage with doing the same thing without a helper could give you an idea how this stuff works.

这篇关于我应该在JavaScript中连接到子原型属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆