What is the reason to use the 'new' keyword at Derived.prototype = new Base

constructor, javascript, prototype

Solution

WeatherWidget.prototype = new Widget;

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.)

But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).

This way, your `WeatherWidget` instances will all inherit from the same `Widget` instance. The prototype chain will be:

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

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.

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;

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.

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] → …

In implementations of ECMAScript Ed. 5 and later, you can and should use

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

instead. This has the additional advantage that the resulting `constructor` property is not writable, enumerable, or configurable.

The parent constructor will only be called if you call it explicitly, from `WeatherWidget`, for example with

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

See also `Function.prototype.extend()` in my JSX:object.js for how to generalize this. Using that code, it would become

WeatherWidget.extend(Widget);

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"
});

would be equivalent to

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

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.

Problem

What does the following code do: ``` WeatherWidget.prototype = new Widget; ``` where `Widget` is a constructor, and I want to extend the Widget 'class' with a new function `WeatherWidget`. What is the `new` keyword doing there and what would happen if it is left out?

Original source

Related problems