javascript - 使用 .prototype 和 __proto__ 创建子类

标签 javascript

我最近一直在通过编写一些 gnome shell 扩展来学习 javascript,因此我对 Javascript 的理解受到了我在 gnome-shell javascript 源代码中观察到的示例的影响。我有一种感觉,我对类的理解是错误的,只是想得到一些澄清。

我已经编写了一些自己的子类,并且在每种情况下,我都通过遵循 gnome-shell javascript 源代码中的类似代码来简单地定义它们:

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 方法。

我最近尝试应用相同的方法来创建 Clutter.Actor 的子类(重要的是它不是 GNOME shell 定义的类),并意识到上述子类化对象的方式不是标准的。首先,并非每个类都像我假设的那样具有 _init 函数;这只是 GNOME-shell 在其 javascript 类中所做的事情。

所以,我的问题是:

  1. 是否有关于上述创建子类方法的文档?我见过的所有教程都说要设置 Subclass.prototype = new Superclass() 而不是执行 Subclass.prototype = { __proto__:Superclass.prototype, define_prototype_methods_here } 方法, 但我的想法是,如果 gnome-shell 一直使用它,一定有一些方法吗?
  2. 如果我想尽可能接近上述定义类的方式(这样我就可以保留一些与我正在为其编写扩展的 GNOME-shell 的代码相似性),我要替换什么 Superclass.prototype._init.call(this)Subclass._init 中的 以确保 Subclass.prototype 获取所有方法/Superclass 的属性(然后我将其添加到我的 Subclass.prototype 定义中),如果 Superclass 没有 _init 函数(即它是否具有我调用的某些等效构造函数)?

我对这一切真的很困惑,所以如果我的问题没有多大意义,请原谅我;这将是因为我的误解和困惑的程度!

编辑:说明: - 我知道不推荐使用 __proto__ 因为它是非标准的,但我的代码永远不会在浏览器中运行 - 它只会与 GNOME javascript(基本上是 Mozilla javascript)一起运行引擎),因此我无需担心交叉兼容性问题。

最佳答案

如前所述,不要使用 __proto__这是一个非标准属性。 (现在浏览器中的 JavaScript 已对其进行标准化。仍然不要使用它。) 但是

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

也不是一个很好的方法。如果 Superclass 需要参数怎么办?

您有更好的选择。

ES2015及以上

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

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();

ES5 及更早版本

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

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

然后在 Subclass 中,您调用 Superclass 并使用 this 引用该对象,以便它有机会初始化:

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 及更早版本

ES3 和更早的版本没有 Object.create,但您可以轻松地编写一个函数来以几乎相同的方式为您设置原型(prototype):

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

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

然后你做与我们的 ES5 示例相同的事情:

完整示例:

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();

关于javascript - 使用 .prototype 和 __proto__ 创建子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10580158/

相关文章:

javascript - 使用文件夹路径名,保存所有图像文件和文件名

javascript - 使用文本框动态取消选中容器中的所有复选框

javascript - Sanctuary Js 和定义逆变仿函数

javascript - 引用/解析对象

javascript - 如何检查谁邀请了谁 Discord.js

Javascript 数组到 php 的 post

Javascript/JQuery : browse through an array and put elements inside a div

javascript - 访问内容页面元素

javascript - 通过删除隐藏的 div 执行干净的提交

javascript - 将一个函数作为另一个函数的参数传递给嵌套函数