我最近一直在通过编写一些 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 类中所做的事情。
所以,我的问题是:
- 是否有关于上述创建子类方法的文档?我见过的所有教程都说要设置
Subclass.prototype = new Superclass()
而不是执行Subclass.prototype = { __proto__:Superclass.prototype, define_prototype_methods_here }
方法, 但我的想法是,如果 gnome-shell 一直使用它,一定有一些方法吗? - 如果我想尽可能接近上述定义类的方式(这样我就可以保留一些与我正在为其编写扩展的 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/