使用.prototype和__proto__创建子类 [英] Making subclass with .prototype and __proto__

查看:98
本文介绍了使用.prototype和__proto__创建子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近通过编写一些gnome shell扩展来学习javascript,因此我对Javascript的理解已经被我在gnome-shell javascript源中观察到的例子所塑造。我有一种感觉,我一直在理解错误,只是想澄清一些。

I've recently been learning javascript by writing some gnome shell extensions, and hence my understanding of Javascript has been shaped by the examples I've observed in the gnome-shell javascript sources. I have a feeling I've been understanding classes wrong and just want some clarification.

我写了几个自己的子类,并且在每种情况下我都是只需通过跟随gnome-shell javascript源代码中的类似代码来定义它们:

I've written a few of my own subclasses, and in each case I've defined them simply by following similar code in the gnome-shell javascript source:

Subclass = function() {
    this._init.apply(this,arguments);
}
Subclass.prototype = {
    __proto__: Superclass.prototype,
    _init: function() {
        Superclass.prototype._init.call(this);
    },
    // add other methods of Subclass here.
}

到目前为止,我认为这是制作课程的标准方式 Subclass 基本上是 Superclass 加上额外内容。我假设每个对象都有 _init 方法。

Up to now I thought this was the standard way of making a class Subclass that was basically Superclass plus extras. I assumed that every object had a _init method.

我最近尝试使用相同的方法制作 Clutter.Actor 的子类(重要的是它不是GNOME-shell定义的类),并且意识到上面的子类化对象的方式不是标准。首先,并非每个类都有我假设的 _init 函数;这只是GNOME-shell在他们的javascript类中完成的事情。

I've recently tried to apply the same method to make a subclass of a Clutter.Actor (what's important is that it's not a GNOME-shell-defined class), and realised that the above way of subclassing objects is not the standard. For one, not every class has a _init function as I assumed; this is just something that GNOME-shell has done in their javascript classes.

所以,我的问题是


  1. 是否有关于上述创建子类的方法的文档?我见过的所有教程都说设置 Subclass.prototype = new Superclass()而不是做 Subclass.prototype = {__proto __:Superclass。 prototype,define_prototype_methods_here} 方法,但我的想法是,如果gnome-shell一直使用它,必须有一些方法吗?

  2. 如果我想留下来尽可能接近上面定义类的方式(这样我可以保留一些代码与GNOME-shell的相似性,我正在编写扩展),我要替换什么 Superclass.prototype._init。在 Subclass._init 中调用(this) 以确保 Subclass.prototype 获取 Superclass 的所有方法/属性(然后我在 Subclass.prototype ),如果超类没有 _init 函数(即它是否有一些等效的构造函数我电话)?

  1. Is there any documentation regarding the above method of creating subclasses? All the tutorials I've seen say to set Subclass.prototype = new Superclass() instead of doing the Subclass.prototype = { __proto__:Superclass.prototype, define_prototype_methods_here } method, but my thought is that there must be some method to it if gnome-shell uses it consistently?
  2. If I wanted to stay as close as possible to the above way of defining classes (just so I can retain some code similarity to GNOME-shell for which I am writing extensions), what do I replace Superclass.prototype._init.call(this) with in Subclass._init to make sure that the Subclass.prototype gets all the methods/properties of Superclass (which I then add on to in my definition of Subclass.prototype), if the Superclass doesn't have an _init function (i.e. does it have some equivalent constructor function I call)?

我真的很好如果我的问题没有多大意义,那么请原谅我。这是因为我误解的程度和困惑!

I'm really confused about this all so please forgive me if my question doesn't make much sense; it'll be because of the extent of my misunderstanding & confusion!

编辑:澄清:
- 我知道 __ proto __ 不建议使用,因为它是非标准的,但我的代码永远不会在浏览器中运行 - 它只会运行GNOME javascript(基本上是Mozilla javascript引擎),所以我不需要担心交叉兼容性。

EDIT: clarification: - I know the __proto__ is not recommended because it is non-standard, but my code is never going to run in a browser - it's only ever going to run with GNOME javascript (which is basically the Mozilla javascript engine), so I don't need to worry about cross-compatibility.

推荐答案

如前所述,不要使用 __ proto __ 这是一个非标准的属性。 (现在浏览器中的JavaScript标准化了。仍然不使用它。)但是

As already said, don't use __proto__. It's a non-standard property. (It's standardized for JavaScript in browsers now. Still don't use it.) But

Subclass.prototype = new Superclass(); // Don't do this

也不是一个非常好的方法。如果超类需要参数怎么办?

is not a very good method either. What if Superclass expects parameters?

你有更好的选择。

class 为您处理所有这些管道;完整示例:

class handles all of this plumbing for you; complete example:

class Superclass {
    constructor(superProperty) {
        this.superProperty = superProperty;
    }
    method() {
        console.log("Superclass's method says: " + this.superProperty);
    }
}
class Subclass extends Superclass {
    constructor(superProperty, subProperty) {
        super(superProperty);
        this.subProperty = subProperty;
    }
    method() {
        super.method(); // Optional, do it if you want super's logic done
        console.log("Subclass's method says: " + this.subProperty);
    }
}

let o = new Subclass("foo", "bar");
console.log("superProperty", o.superProperty);
console.log("subProperty", o.subProperty);
console.log("method():");
o.method();

Subclass.prototype 继承自 Superclass.prototype 只。这可以通过例如ES5的 Object.create 来完成:

Let Subclass.prototype inherit from Superclass.prototype only. This can be done for example with ES5's Object.create:

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

然后在 Subclass 中,你打电话给超类引用该对象,以便它有机会初始化:

And then in Subclass, you call Superclass with this referring to the object so it has a chance to initialize:

function Subclass() {
    Superclass.call(this); // Pass along any args needed
}

完整示例:

function Superclass(superProperty) {
    this.superProperty = superProperty;
}
Superclass.prototype.method = function() {
    console.log("Superclass's method says: " + this.superProperty);
};
function Subclass(superProperty, subProperty) {
    Superclass.call(this, superProperty);
    this.subProperty = subProperty;
}
Subclass.prototype = Object.create(Superclass.prototype);
Subclass.prototype.constructor = Subclass;

Subclass.prototype.method = function() {
    Superclass.prototype.method.call(this); // Optional, do it if you want super's logic done
    console.log("Subclass's method says: " + this.subProperty);
};

var o = new Subclass("foo", "bar");
console.log("superProperty", o.superProperty);
console.log("subProperty", o.subProperty);
console.log("method():");
o.method();

ES3及更早版本不包括有 Object.create ,但你可以很容易地编写一个为你设置原型的函数:

ES3 and earlier don't have Object.create, but you can easily write a function that sets up the prototype for you in much the same way:

function objectCreate(proto) {
    var ctor = function() { };
    ctor.prototype = proto;
    return new ctor;
}

(注意:您可以半垫片对象。通过创建只接受一个参数的一个来创建,但是 Object.create 的多参数版本不能被填充,所以它会给其他页面上的代码错误的想法,如果它也使用 Object.create 。)

(Note: You could half-shim Object.create by creating one that takes only one argument, but the multiple-argument version of Object.create cannot be shimmed, so it would be giving other code on the page the wrong idea if it also uses Object.create.)

然后你做同样的事情作为我们的ES5示例:

Then you do the same thing as our ES5 example:

完整示例:

function objectCreate(proto) {
    var ctor = function() { };
    ctor.prototype = proto;
    return new ctor;
}

function Superclass(superProperty) {
    this.superProperty = superProperty;
}
Superclass.prototype.method = function() {
    console.log("Superclass's method says: " + this.superProperty);
};
function Subclass(superProperty, subProperty) {
    Superclass.call(this, superProperty);
    this.subProperty = subProperty;
}
Subclass.prototype = objectCreate(Superclass.prototype);
Subclass.prototype.constructor = Subclass;

Subclass.prototype.method = function() {
    Superclass.prototype.method.call(this); // Optional, do it if you want super's logic done
    console.log("Subclass's method says: " + this.subProperty);
};

var o = new Subclass("foo", "bar");
console.log("superProperty", o.superProperty);
console.log("subProperty", o.subProperty);
console.log("method():");
o.method();

这篇关于使用.prototype和__proto__创建子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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