What Is the Reason to Use the 'New' Keyword At Derived.Prototype = New Base

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

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.

Why would using new and constuctor functions in JavaScript be wrong

using new and constructor functions is wrong and should not be used.

Read Is JavaScript's "new" keyword considered harmful? - No, it is not. A few (correct) arguments are

  • It's confusing to newbies because of hiding the prototypical concept. To quote @Aadit:

    [With new] the constructor function becomes simpler. However it becomes very
    difficult to explain prototypal inheritance to a person who knows
    nothing about it. It becomes even more difficult to explain it to a
    person who knows classical inheritance.

  • Constructors do silently fail when forgetting new
  • In a few instances, the pure Object.create approach is cleaner
  • Building a class hierarchy is complicated and often done wrong

However, once you understand these, new is harmless. Actually, every time you need instance initialisation plus prototypical inheritance, constructors with new are the way to go.

They go against the prototype nature of JavaScript.

This will never change. I hardly can imagine why anyone would criticise this, prototypical inheritance is far more powerful than class inheritance. Probably they are only arguing against the syntax.

Could someone please enlighten me and show a situation where using new and constructor functions is so bad it should never be used?

It should not be used when not needed. Singletons can easily be created using the module pattern and object literals; inheritance does not help here. See Is it right to think of a Javascript Function Expression that uses the 'new' keyword as 'static' for an example.

inheritance using prototype in javascript

An explanation would be:

Prototypes are live chains between objects. Because B's prototype is a single tone instance of A, the array prop is passed by reference. This means that for each B instance we have access to the same A instance on the prototype. This might sound confusing at first but that's the magic of prototypes in JavaScript.

This is the caveat of prototypal inheritance. Anything on the prototype will be passed down to each instance. To maintain different instances of the attribute we initialise our object's attributes in the constructor.

When working with objects in JS (like arrays), they are passed by reference.

To make use of JS's prototype system I would suggest something like so:

function A(){
this.text = "";

this.action = function(){
this.text+="z";
this.arr.push(1);
}

this.test = function(){
console.log(this.text+"|"+this.arr);
}
}

function B(){
this.arr = [];
}

B.prototype = new A();

This way we reuse the methods from the "parent" and have a localised array in our "child". At a first glance this might look as a classic OOP inheritance case but it is a bit different.

If you want to read more about prototypes in JS I recommend this article

Hope this helps.

Trying to understand inheritance in JavaScript -- what's going on here?

Object.create(Animal); // set Cat's prototype to Animal

Yes, but to the Animal constructor function (or, to be exact: to a new object inheriting from that function object - check the docs for Object.create). That's hardly what you want - and explains your curious result of saying "Animal", as that's the Animal function's name property.

Instead, you want to build a prototype chain, so that cat instances inherit from Cat.prototype which inherits from Animal.prototype (which inherits from Object.prototype):

Cat.prototype = Object.create(Animal.prototype);

Also, for prototypical inheritance, you should but the sayName and sayType methods on the prototype object (and only once):

Animal.prototype.sayType = function() {
alert(this.type);
};
Cat.prototype.sayName = function() { // after creation of that object, of course
alert(this.name);
};

Why are the object and constructor.prototype set to Base in JavaScript?

Have a look at Why [not] to use the new keyword here?. You might not use it and create a new instance of it, but rather just inherit from Base.prototype.

Also the constructor.prototype is Base. Why not Shape?

I'm not sure which constructor you are referring to here:

  • The constructor property of all your objects is Base, as all of them inherit this prototype from the Base.prototype object. You did not overwrite it after setting up the inheritance chains. It is not really necessary, but good style: Shape.prototype.constructor = Shape and Rectangle.prototype.constructor = Rectangle - where those prototype objects are the overwritten ones which inherit from Base.

  • The constructor parameter of your instanceOf function. You pass in Rectangle there, so constructor.prototype is the prototype object of Rectangle, which inherits from Base but is different.

When I check the value of rec in the debug mode, the object is Base { x=0, y=0, w=10, more...}

Usually not. Is Base something special, e.g. a host object? Your rec object is an instance of Base, so it might be displayed differently because of that.

rec is just an object which inherits from Rectangle.prototype which inherits from Shape.prototype which inherits from Base.prototype which inherits from​… Assuming Base is the function you defined, from Object.prototype which inherits from null.

B extends A, but B.add populates A.prototype.property

There is only one children array created in your script, but it is referenced by each instance (and even B's prototype) due to inheritance. When you push to it, you will see the changes from everywhere as well.

Instead, give every instance its own array:

function A() {
this.children = [];
}

And also, don't create only one array for all B instances to inherit from with new A - instead, use

function B() {
A.call(this); // do everything the A constructor does on this instance
}
B.prototype = Object.create(A.prototype);
B.prototype.addChild = function(Child) {
this.children.push(Child);
};

What is a practical advantage of Object.create over Constructor function?

Calling a constructor function:

 const child = new Human();

is (nearly) the same as:

 const child = Object.create(Human.prototype);
Human.call(child);

therefore I would not see Object.create as a language feature, but rather as a way to understand prototypal inheritance in JS.

There are very very limited usecases for prototype chains without constructors. One example would be the deserialization of a Human:

 const serialized = JSON.stringify(child); // Human inheritance gets lost, its a plain object now

const child2 = Object.assign(Object.create(Human.prototype), JSON.parse(serialized));

What is the correct prototype affectation in javascript inheritance?

Derived.prototype = new Base();

This does call the Base constructor just for setting up the prototype chain. While sometimes working and giving equivalent results to Object.create, it is error-prone and should be avoided. Read What is the reason to use the 'new' keyword at Derived.prototype = new Base (and why it should not be used).

Derived.prototype = Object.create(Base.prototype);

This is state of the art - Correct javascript inheritance so to say.

Derived.prototype = Base.prototype;

This is plain wrong. Do not use. It lets Base and Derived instances inherit from the same object - while it (seldom) can be helpful to have multiple constructors for a "class", this is not "subclassing".

Is Derived.prototype.constructor = Derived; really needed? Why?

It can be omitted and your script will work nonetheless, but for convenience you would expect that (new Derived).constructor === Derived. Also have a look at JavaScript inheritance and the constructor property



Related Topics



Leave a reply



Submit