471,353 Members | 1,409 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,353 software developers and data experts.

Extending Error

Hi,

I thought it would be a good idea to make specialised error objects. So
I did something like this:

function IndexOutOfBoundsException(message)
{
Error.call(this, message);
}

IndexOutOfBoundsException.prototype = new Error();
....
throw new IndexOutOfBoundsException("bla");

I expected that I could use error.message after throwing
IndexOutOfBoundsException to retrieve the error message, but that
doesn't work. I just get an uncaught exception: Error.

Of course I can do
function IndexOutOfBoundsException(message)
{
this.message = message;
}

But I felt that the first example was better because
IndexOutOfBoundsException should have everything that an Error has.

Any comments why the first example does not work is appreciated.
May 1 '06 #1
9 2093
VK

Robert wrote:
Hi,

I thought it would be a good idea to make specialised error objects. So
I did something like this:

function IndexOutOfBoundsException(message)
{
Error.call(this, message);
}

IndexOutOfBoundsException.prototype = new Error();
...
throw new IndexOutOfBoundsException("bla");

I expected that I could use error.message after throwing
IndexOutOfBoundsException to retrieve the error message, but that
doesn't work. I just get an uncaught exception: Error.

Of course I can do
function IndexOutOfBoundsException(message)
{
this.message = message;
}

But I felt that the first example was better because
IndexOutOfBoundsException should have everything that an Error has.

Any comments why the first example does not work is appreciated.


If you define the error message right at the moment of call:
throw new IndexOutOfBoundsException("bla");
then what the practical use of it? Just to tell "look'ma, OOP stuff"?
:-) With the same success you could just
throw new Error("blah")
It would be much simplier.

If you want to imitate Java/C++ or maybe extend the error with extra
info - and following the unbreakable KISS principles - you could:

function ErrorFactory(message, longdesc) {
var err = new Error(message);
err.longdesc = 'This kind of error happens if ...';
return err;
}

function IndexOutOfBoundsException() {
return ErrorFactory(
'Index is out of bounds',
'This kind of error happens if ...');
}
try {
throw IndexOutOfBoundsException();
}
catch(e) {
alert(e.message);
alert(e.longdesc);
}

May 2 '06 #2
VK wrote:
Robert wrote:
Hi,

I thought it would be a good idea to make specialised error objects. So
I did something like this:

function IndexOutOfBoundsException(message)
{
Error.call(this, message);
}

IndexOutOfBoundsException.prototype = new Error();
...
throw new IndexOutOfBoundsException("bla");


If you define the error message right at the moment of call:
throw new IndexOutOfBoundsException("bla");
then what the practical use of it? Just to tell "look'ma, OOP stuff"?


Well you could do something like:

try {
var first = list.get(0);
}
catch (e) {
if (e instanceof IndexOutOfBoundsException)
return 0;
else
throw e;
}

But more importantly I just don't understand why my code does not work
and I do want to understand.

May 2 '06 #3
VK

Robert wrote:
Well you could do something like:

try {
var first = list.get(0);
}
catch (e) {
if (e instanceof IndexOutOfBoundsException)
return 0;
else
throw e;
}

But more importantly I just don't understand why my code does not work
and I do want to understand.


I don't know exactly - maybe because you're creating an instance of an
intrinsic object (Error) and implant this instance into the deep of
your own constructor chain. To trace all relations and the path of the
constructor call - it takes a pensil, a paper and some time of deep
thinking :-)

Some may comment on why it doesn't work (whatever "work" and "doesn't
work" means here).

As a humble suggestion I would just keep custom objects by their own,
in the chain of extension and the general task of each one.

<script type="text/javascript">

function Exception(num,mes) {
Error.call(this);
this.type = 'Exception';
}

function BadMoodException(num, mes) {
Exception.call(this);
this.number = 666;
this.longdesc = "I'm not moody today.";
}

function IDontLikeYouException() {
BadMoodException.call(this);
this.message = "Some weird exception";
this.longdesc+= " And goblins got me."
}

function BoringStuff() {
}
BoringStuff.prototype.lastDrop = function() {
throw new IDontLikeYouException();
}
try {
var bs = new BoringStuff();
bs.lastDrop();
}
catch(e) {
alert(e.type);
alert(e.number);
alert(e.message);
alert(e.longdesc);
alert(e instanceof IDontLikeYouException);
}
</script>

May 2 '06 #4
VK wrote:
Robert wrote:
But more importantly I just don't understand why my code does not work
and I do want to understand.

Some may comment on why it doesn't work (whatever "work" and "doesn't
work" means here).


"Work" means that the message property has been set, and "doesn't work"
means that it has not been set.
As a humble suggestion I would just keep custom objects by their own,
in the chain of extension and the general task of each one.

<script type="text/javascript">

function Exception(num,mes) {
Error.call(this);
this.type = 'Exception';
}


If Error.call(this, message) doesn't set the message then I don't this
it is useful to do Error.call(this) at all.
To keep the Exception an Error I think it's best to set the prototype.

The rest of the code isn't really related to my question.
May 3 '06 #5
VK

Robert wrote:
<script type="text/javascript">

function Exception(num,mes) {
Error.call(this);
this.type = 'Exception';
}
If Error.call(this, message) doesn't set the message then I don't this
it is useful to do Error.call(this) at all.


That was copy'n'paste error. In the ground-zero constructor you make
just generic Error object to fill up accordingly further in the chain.
Or you can overload constructor (it is not obligated to return "this"
every time) :

function Exception(num,mes) {
var err = new Error(num,mes);
err.type = 'Exception';
return err;
}
<the rest of code as originally posted>

To keep the Exception an Error I think it's best to set the prototype.


IMHO you are still trying to complicate your life while JavaScript was
build to make it as easy as possible :-)

As a hint: "throw" statement doesn't require Error object at all. You
can throw and catch anything: Error's, String's, Number's, Boolean's,
your own objects.
For fun of it you can throw the whole object out of itself on error.
For serious you can throw a string property of your object:
....
this.ErrorMessage = "Something wrong";
....
throw this.ErrorMessage;

May 3 '06 #6
VK wrote:

function Exception(num,mes) {
var err = new Error(num,mes);
err.type = 'Exception';
return err;
}

IMHO you are still trying to complicate your life while JavaScript was
build to make it as easy as possible :-)

As a hint: "throw" statement doesn't require Error object at all.


I know. Still it is a good convention to throw something that is an Error.

Anyway I don't feel

function MyException(message) {
this.message = message;
}
MyException.prototype = new Error(); //or clone(Error.prototype)

complicates my life and is more complicated than your example.

However I think all this is off-topic. All I wanted to know is why
Error.call(this, message) didn't work.
May 3 '06 #7
VK

Robert wrote:
However I think all this is off-topic. All I wanted to know is why
Error.call(this, message) didn't work.


Besause intrinsic constructors has to be called explicetly as
constructors - with new keyword. Also all intrinsic objects have a
prototype property that is read-only. Some new *functionality* (read:
property or method) may be added to the prototype, but the object may
not be assigned a different prototype.

On a higher level: as I originally said: because you have to choose
between a la class-based inheritance and prototype inheritance.
JavaScript allows both, but using it in a cocktail is a call for
troubles. A "rule of thumb": if you have in one code both .prototype.
manipulations and new || call || apply then something is possibly
wrong with your code.

This works:

function IndexOutOfBoundsException(mes) {
return new Error(mes);
}

try {
throw new IndexOutOfBoundsException('blah');
}
catch(e) {
alert(e.message);
}

May 3 '06 #8
Robert wrote:
<snip>
... . All I wanted to know is why
Error.call(this, message) didn't work.


It doesn't work because of:-

<quote cite="Ecma 262, 3rd Ed. Section 15.11.1">
15.11.1 The Error Constructor Called as a Function

When Error is called as a function rather than as a constructor, it
creates and initialises a new Error object. Thus the function call
Error(...) is equivalent to the object creation expression
new Error(...) with the same arguments.
</quote>

If calling the Error constructor as a function does the same as using it
as the operand of the - new - operator calling it as a method (which is
effectively what the - call - method does)is going to do the same;
constructing a new Error object and returning it.

Error.call(this, message)

is the equivalent of:-

new Error(message);

- and then you throw the newly created Error object away.

(Incidentally, don't expect to learn anything from VK, he doesn't really
know what he is doing hiself, and makes it up out of thin air.)

Richard.
May 3 '06 #9
Richard Cornford wrote:
Robert wrote:
<snip>
... . All I wanted to know is why
Error.call(this, message) didn't work.

It doesn't work because of:-

<quote cite="Ecma 262, 3rd Ed. Section 15.11.1">
15.11.1 The Error Constructor Called as a Function

When Error is called as a function rather than as a constructor, it
creates and initialises a new Error object. Thus the function call
Error(...) is equivalent to the object creation expression
new Error(...) with the same arguments.
</quote>


Thanks for your explanation!
May 4 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

17 posts views Thread by cwdjrxyz | last post: by
8 posts views Thread by Mark Olbert | last post: by
4 posts views Thread by Divick | last post: by
5 posts views Thread by vbgunz | last post: by
9 posts views Thread by Fat Elvis | last post: by
4 posts views Thread by Ian Richardson | last post: by
3 posts views Thread by katis | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.