Inheritance from native objects

It seems that I missed something about inheriting the constructor chain in Javascript using native objects. For instance:

function ErrorChild(message) { Error.call(this, message); } ErrorChild.prototype = Object.create(Error.prototype); var myerror = new ErrorChild("Help!"); 

Why is myerror.message defined as "" after these statements? I would expect the Error constructor to define it as "Help!". (and override the default Error.prototype.message ), for example, if I do:

 var myerror = new Error("Help!") 

Thanks a lot!

+6
source share
2 answers

Easy Workaround: Working Script

 function ErrorChild(name, message) { // Error.call(this); this is not needed this.name = name; this.message = message; } ErrorChild.prototype = Object.create(Error.prototype); ErrorChild.prototype.constructor = ErrorChild; var myerror = new ErrorChild("test", "Help!"); document.body.innerHTML += myerror.message; 

The above does not violate the expected behavior. When you throw myerror , the correct name and message will be displayed.

Problem

From the ECMA5 language specification:

15.11.1 Error constructor called as a function

When an Error is called as a function, and not as a constructor, it creates and initializes a new Error object. Thus, the call to the Error (...) function is equivalent to the expression for creating the new Error (...) object with the same arguments.

Problem: Error.call(this) , is the equivalent of new Error . But when creating a new Error , the name or message value will not be set. new Error will initialize message with "" by default.

11.15.4.3 Error.prototype.message # Ⓣ Ⓡ The original value of Error.prototype.message is an empty string.

Test

If inside your ErrorChild you should add:

 var test = Error.call(this, message); console.dir(test); console.log(test instanceof Error); // true; console.log(test.message); // "Help!"; 

test reflects the ECMA5 specification. An instance of Error with the correct message .

Output:

Because Error.call(arguments); automatically translated into new Error(arguments); , scope is lost, so properties are never initialized in the this object.

When Object.create(Error.prototype) , the message property accepts the default value, an empty string.

+4
source

The problem is not in the inheritance chain, but in that the Error call as a function behaves like a constructor call, creating an instance of new Error Object

Therefore, when calling new ErrorChild executable code is actually equivalent

 function ErrorChild(message) { new Error (message) } 

Wait. But this only creates a new Error object, which is not used everywhere (and also is not returned by your constructor). And just forgot.

Thus, it does not actually change the actual instance of ErrorChild .

Therefore, the message property that you are accessing is the one that is shaded by ErrorChild.prototype , which inherits from Error.protyotype and therefore contains the message value by default, the empty string ""

But you can just "mimic" the Error object.

As you only need toString method for determining behavior and 2 properties

  • name
  • message

To cover the standard Error properties.

You can simply set the prototype of your constructors in Error.prototype and assign name and message manually.

 function ErrorChild (name,message) { this.name = name; this.message = message; } ErrorChild.prototype = Error.prototype; 

Now you can simply create an instance of new ErrorChild (...) .

What can you throw around log and catch

throw new ErrorChild("CustomError","Help") //Uncaught CustomError: Help

Heres a JSBin Demo

+1
source

Source: https://habr.com/ru/post/944850/


All Articles