在 Derived.prototype = new Base 使用“new"关键字的原因是什么
下面的代码做了什么:
WeatherWidget.prototype = new Widget;
其中 Widget
是一个构造函数,我想用一个新函数 WeatherWidget
扩展 Widget 'class'.
where Widget
is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget
.
new
关键字在那里有什么作用?如果省略它会发生什么?
What is the new
keyword doing there and what would happen if it is left out?
推荐答案
WeatherWidget.prototype = new Widget;
new
关键字调用 Widget
作为构造函数,并将返回值分配给 prototype
属性.(如果省略 new
,则不会调用 Widget
,除非添加参数列表 ()
.但是,调用 Widget
这种方式可能是不可能的.如果它不是严格模式代码并且实现符合 ECMAScript Ed. 5.x 那里,它肯定有可能破坏全局命名空间,因为构造函数中的 this
将引用 ECMAScript 的全局对象.)
The new
keyword calls Widget
as a constructor and the return value is assigned to the prototype
property. (If you would omit new
, you would not call Widget
unless you added an argument list, ()
. However, calling Widget
that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this
in the constructor would refer to ECMAScript’s global object.)
但是这个方法其实来自一个真的病毒 不好的例子 在旧的 Netscape JavaScript 1.3 指南中(反映在 Oracle,以前的 Sun)中.
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
这样,您的 WeatherWidget
实例都将继承自 same Widget
实例.原型链将是:
This way, your WeatherWidget
instances will all inherit from the same Widget
instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
这可能很有用,但大多数时候您不希望它发生.除非您希望所有 WeatherWidget
实例在它们之间共享它们从该 Widget<继承的 属性值,否则您不应该在此处这样做/code> 实例,并且仅通过它,来自
Widget.prototype
.另一个问题是您需要以这种方式调用父构造函数,这可能不允许像您那样在没有参数的情况下调用,或者无法正确初始化.它当然与模拟基于类的继承(例如来自 Java)无关.
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget
instances to share among them the property values they inherit from this Widget
instance, and only through it, from Widget.prototype
. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
在这些基于原型的语言中实现基于类的继承的正确方法是(最初由 Lasse Reichstein Nielsen 在 2003 年的 comp.lang.javascript
中,用于克隆对象):
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript
in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
constructor
原型属性也应该是固定的,这样你的 WeatherWidget
实例 w
就会有 w.constructor === WeatherWidget
符合预期,而不是 w.constructor === Widget
.但是,请注意它是可枚举的.
The constructor
prototype property should be fixed as well, so that your WeatherWidget
instances w
would have w.constructor === WeatherWidget
as expected, and not w.constructor === Widget
. However, be aware that it is enumerable afterwards.
这样,WeatherWidget
实例会通过原型链继承属性,但不会在它们之间共享属性值,因为它们是通过继承自
:Widget.prototype
的没有自己属性的虚拟
This way, WeatherWidget
instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype
through Dummy
which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
在 ECMAScript Ed 的实现中.5 及更高版本,您可以并且应该使用
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
相反.这具有额外的优点,即生成的 constructor
属性是 不可写、不可枚举或不可配置.
instead. This has the additional advantage that the resulting constructor
property is not writable, enumerable, or configurable.
只有当你从 WeatherWidget
显式调用父构造函数时才会调用它,例如使用
The parent constructor will only be called if you call it explicitly, from WeatherWidget
, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
另见 Function.prototype.extend()
在我的 JSX:object.js 了解如何概括这一点.使用该代码,它将变成
See also Function.prototype.extend()
in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
我的 Function.prototype.extend()
采用可选的第二个参数,您可以使用它轻松地扩充 WeatherWidget
实例的原型:
My Function.prototype.extend()
takes an optional second argument with which you can easily augment the prototype of WeatherWidget
instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
相当于
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
不过,您仍然需要在子构造函数中显式调用父构造函数;该部分不能合理地自动化.但是我的 Function.prototype.extend()
向 Function
实例添加了一个 _super
属性,这使它更容易:
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend()
adds a _super
property to the Function
instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
其他人也实现了类似的扩展.
Other people have implemented similar extensions.
相关文章