一尘不染

JavaScript在Derived.prototype = new Base上使用'new'关键字的原因是什么

javascript

以下代码是做什么的:

WeatherWidget.prototype = new Widget;

Widget构造函数在哪里,我想用新函数扩展Widget的“类” WeatherWidget

什么是 new 关键词在那里做,如果它被省略了,会发生什么?


阅读 264

收藏
2020-04-23

共1个答案

一尘不染

WeatherWidget.prototype = new Widget;

new关键字调用Widget构造函数,返回值分配给prototype属性。(如果省略newWidget除非添加了参数列表,否则将不会调用()。但是,以Widget这种方式调用可能是不可能的。如果它不是严格的模式代码并且实现是,则肯定有可能
破坏全局名称空间。 符合ECMAScript版本5.x,因为this在构造函数中它将引用ECMAScript的全局对象。)

这样,您的WeatherWidget实例将全部从 同一个 Widget实例继承。原型链将为:

[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …

这可能很有用,但是大多数时候您都不希望发生这种情况。除非您希望所有WeatherWidget实例 在它们之间共享 从该实例(仅 通过
该实例)继承的 属性值
,否则不要在此进行操作。另一个问题是您需要以这种方式调用父构造函数,这可能不允许像您一样在没有参数的情况下调用它,或者无法正确初始化。它与模拟类(例如从Java)继承的继承毫无关系。Widget
__Widget.prototype

function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;

constructor原型属性应该是固定的为好,这样你的WeatherWidget情况下,w将有w.constructor === WeatherWidget预期,而不是w.constructor === Widget。但是,请注意,此后是可枚举的。

这样一来,WeatherWidget情况将通过继承原型链的属性,但不会在它们之间共享的属性值,因为他们继承Widget.prototype通过Dummy它没有自己的属性:

[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …

在ECMAScript Ed的实现中。5及更高版本,您可以并且应该使用

WeatherWidget.prototype = Object.create(Widget.prototype, {
  constructor: {value: WeatherWidget}
});

代替。这具有额外的优点,即所得的constructor属性不可写,不可枚举或不可配置。

仅当从中显式调用父构造函数时,才会调用WeatherWidget,例如

function WeatherWidget (…)
{
  Widget.apply(this, arguments);
}

另请参见Function.prototype.extend()我的JSX:object.js中如何将其概括化。使用该代码,它将变成

WeatherWidget.extend(Widget);

My Function.prototype.extend()带有一个可选的第二个参数,您可以使用它轻松地扩展WeatherWidget实例的原型:

WeatherWidget.extend(Widget, {
  foo: 42,
  bar: "baz"
});

相当于

WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";

但是,您仍然需要在子构造函数中显式调用父构造函数。该部分不能合理地自动化。但是我向实例Function.prototype.extend()添加了一个_super属性,Function这使它变得更容易:

function WeatherWidget (…)
{
  WeatherWidget._super.apply(this, arguments);
}

其他人也实现了类似的扩展。

2020-04-23