f



Throw 'Error()' or 'new Error()'?

With custom exceptions, we have to create a new instance before we throw
them:

  function AppError(msg) {
     this.msg = msg; // just an example
  }
  throw new AppError("I did bad");

To throw a StopIteration, on the other hand, we have to throw it directly:

  throw StopIteration;        // object StopIteration
  throw new StopIteration();  // TypeError

With Error, both are possible:

  throw Error("oops");        // object Error
  throw new Error("oops");    // object Error

I've seen both forms a number of times now. AppError and Error are
functions (StopIteration is an object), so I'd normally say "throw new
Error()" was the preferred form. We couldn't just "throw AppError(msg)"
because that would set |msg| on the global object, but this doesn't
happen with Error, so "throw Error(msg)" should be ok. Any thoughts
about this?

(BTW, StopIteration is a rather unusual object: it can't be called or
instanced, but is apparently an instance of itself. StopIteration
instanceof StopIteration == true)


  - Conrad
0
Conrad
6/5/2009 4:55:28 PM
comp.lang.javascript 38370 articles. 2 followers. javascript4 (1315) is leader. Post Follow

10 Replies
1333 Views

Similar Articles

[PageSpeed] 16

Conrad Lender wrote:

> With Error, both are possible:
> 
>   throw Error("oops");        // object Error
>   throw new Error("oops");    // object Error
> 
> I've seen both forms a number of times now. AppError and Error are
> functions (StopIteration is an object), so I'd normally say "throw new
> Error()" was the preferred form. We couldn't just "throw AppError(msg)"
> because that would set |msg| on the global object, but this doesn't
> happen with Error, so "throw Error(msg)" should be ok. Any thoughts
> about this?

The spec (ECMAScript edition 3) says:

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

so with Error you are free to do
   Error(...)
or
   new Error(...)
-- 

	Martin Honnen
	http://msmvps.com/blogs/martin_honnen/
0
Martin
6/5/2009 5:10:54 PM
Conrad Lender wrote:
> With custom exceptions, we have to create a new instance before we throw
> them:
> 
>   function AppError(msg) {
>      this.msg = msg; // just an example

Yes, this.message would be better.

>   }
>   throw new AppError("I did bad");
> 
> To throw a StopIteration, on the other hand, we have to throw it directly:
> 
>   throw StopIteration;        // object StopIteration
>   throw new StopIteration();  // TypeError
> 
> With Error, both are possible:
> 
>   throw Error("oops");        // object Error
>   throw new Error("oops");    // object Error
> 
> I've seen both forms a number of times now. AppError and Error are
> functions (StopIteration is an object), so I'd normally say "throw new
> Error()" was the preferred form. We couldn't just "throw AppError(msg)"
> because that would set |msg| on the global object, but this doesn't
> happen with Error, so "throw Error(msg)" should be ok. Any thoughts
> about this?

In addition to Martin's answer: ISTM any constructor C can be enabled to be
a factory with

  var _global = this;

  function C()
  {
    var me = arguments.callee;

    if (this.constructor != me)
    {
      var x = new C();
      me.apply(x, arguments);
      return x;
    }
  }

under the provision that C() does not throw exceptions if not enough
arguments are passed (else an iteration of eval("me(...)") would be required).

> (BTW, StopIteration is a rather unusual object: it can't be called or
> instanced, but is apparently an instance of itself. StopIteration
> instanceof StopIteration == true)

What is the purpose of this object?


PointedEars
0
Thomas
6/6/2009 1:31:15 PM
Thomas 'PointedEars' Lahn wrote:

[...]

> In addition to Martin's answer: ISTM any constructor C can be enabled to be
> a factory with
> 
>   var _global = this;
> 
>   function C()
>   {
>     var me = arguments.callee;
> 
>     if (this.constructor != me)
>     {
>       var x = new C();
>       me.apply(x, arguments);
>       return x;
>     }
>   }

It's interesting how this snippet can be fooled, since it relies on a 
public `constructor` property of an object that constructor is being 
called in a context of :)

function Person() {
   var me = arguments.callee;
   if (this.constructor != me) {
     var x = new C();
     me.apply(x, arguments);
     return x;
   }
   this.name = name;
}

Person.call({ constructor: Person }, 'foo'); // undefined

This is a bogus call of course, but it breaks a premise that constructor 
will return a newly constructed object.

[...]

-- 
kangax
0
kangax
6/6/2009 6:02:04 PM
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> In addition to Martin's answer: ISTM any constructor C can be enabled to be
>> a factory with
>>
>>   var _global = this;
>>
>>   function C()
>>   {
>>     var me = arguments.callee;
>>
>>     if (this.constructor != me)
>>     {
>>       var x = new C();

Should have been `me' instead of `C'.  That is, if one wants to remove the
dependency on the declared identifier.  Else `C' should be used instead of
`me' everywhere here.

>>       me.apply(x, arguments);
>>       return x;
>>     }
>>   }
> 
> It's interesting how this snippet can be fooled, since it relies on a 
> public `constructor` property of an object that constructor is being 
> called in a context of :)  [...]

Yes, of course.  In languages as dynamic as these, there are few guarantees.
One cannot even guarantee that me.apply(...) will work as intended even if
`constructor' is right because it may not be supported or be overwritten by
bogus code.


PointedEars
0
Thomas
6/6/2009 6:16:11 PM
On 06/06/09 15:31, Thomas 'PointedEars' Lahn wrote:
> Conrad Lender wrote:
> In addition to Martin's answer: ISTM any constructor C can be enabled
> to be a factory with [snip]

Interesting pattern. It's probably not how Error is implemented
internally (toSource contains "[native code]", at least in FF), but it's
similar.

>> (BTW, StopIteration is a rather unusual object: it can't be called
>> or instanced, but is apparently an instance of itself.
>> StopIteration instanceof StopIteration == true)
> 
> What is the purpose of this object?

It's used with Iterators to signal a 'stop' condition:
https://developer.mozilla.org/En/Core_JavaScript_1.5_Guide/Iterators_and_Generators


  - Conrad


PS: I forgot to thank Martin for his reply, which was spot on. I really
should have thought of that myself.
0
Conrad
6/6/2009 11:12:22 PM
Conrad Lender wrote:
> Thomas 'PointedEars' Lahn wrote:
>> Conrad Lender wrote:
>> In addition to Martin's answer: ISTM any constructor C can be enabled
>> to be a factory with [snip]
> 
> Interesting pattern. It's probably not how Error is implemented
> internally (toSource contains "[native code]", at least in FF),

I wonder why you think that `toSource' is even relevant.  First of all, it
is a proprietary JavaScript method (not defined in, but allowed by
ECMAScript) and secondly, it contains "[native code]" for *all* native
methods, with "native" meaning "not user-defined" here.

> but it's similar.

In fact, reviewing this I think my implementation is unnecessary complicated
and error-prone for most cases.  Since we usually know the maximum number of
arguments the method would handle, and their identifiers per declaration,
the following (here for zero arguments) should suffice:

  function C()
  {
    var me = arguments.callee;

    if (this.constructor != me)
    {
      return new C();
    }
  }

For the Error object as specified in ES3F that would mean

  function Error(message)
  {
    if (this.constructor != arguments.callee)
    {
      return new Error(message);
    }
  }

Of course, this should only be considered pseudo-code with regard to the
ECMAScript implementation and the language it would be written in (probably
C++, as in SpiderMonkey, or Java, as in Rhino).

>>> (BTW, StopIteration is a rather unusual object: it can't be called
>>> or instanced, but is apparently an instance of itself.
>>> StopIteration instanceof StopIteration == true)
>> What is the purpose of this object?
> 
> It's used with Iterators to signal a 'stop' condition:
> https://developer.mozilla.org/En/Core_JavaScript_1.5_Guide/Iterators_and_Generators

The Matrix has you.


PointedEars
0
Thomas
6/6/2009 11:34:06 PM
Conrad Lender wrote:
> Thomas 'PointedEars' Lahn wrote:
>> Conrad Lender wrote: In addition to Martin's answer: ISTM any
>> constructor C can be enabled to be a factory with [snip]
> 
> Interesting pattern. It's probably not how Error is implemented 
> internally (toSource contains "[native code]", at least in FF),

I wonder why you think that `toSource' is even relevant.  First of all,
it is a proprietary JavaScript method (not defined in, but allowed by
ECMAScript) and secondly, it contains "[native code]" for *all* native
methods, with "native" meaning "not user-defined" here.

> but it's similar.

In fact, reviewing this I think my implementation is unnecessary complicated
and error-prone for most cases.  Since we usually know the maximum number of
arguments the method would handle, and their identifiers per declaration,
the following (here for zero arguments) should suffice:

  function C()
  {
    var me = arguments.callee;

    if (this.constructor != me)
    {
      return new me();
    }
  }

For the Error object as specified in ES3F that would mean

  function Error(message)
  {
    var me = arguments.callee;

    if (this.constructor != me)
    {
      return new me(message);
    }
  }

Of course, this should only be considered pseudo-code with regard to the
ECMAScript implementation and the language it would be written in (probably
C++, as in SpiderMonkey, or Java, as in Rhino).

>>> (BTW, StopIteration is a rather unusual object: it can't be called or
>>> instanced, but is apparently an instance of itself. StopIteration
>>> instanceof StopIteration == true)
>> What is the purpose of this object?
> 
> It's used with Iterators to signal a 'stop' condition:
> https://developer.mozilla.org/En/Core_JavaScript_1.5_Guide/Iterators_and_Generators

The Matrix has you!


Regards,

PointedEars
0
Thomas
6/6/2009 11:37:17 PM
On 07/06/09 01:34, Thomas 'PointedEars' Lahn wrote:
> I wonder why you think that `toSource' is even relevant.  First of
> all, it is a proprietary JavaScript method (not defined in, but
> allowed by ECMAScript) and secondly, it contains "[native code]" for
> *all* native methods, with "native" meaning "not user-defined" here.

ad "first")
  I was referring to Firefox in this case (I mentioned that).
ad "second")
  Yes, that's what I meant. I'm not going to dig into the mess that is
Firefox's source code now, but I'm pretty sure that Error is implemented
in C++ instead of JavaScript.

>>>> [StopIteration]
>>> What is the purpose of this object?
>> It's used with Iterators to signal a 'stop' condition: 
>> https://developer.mozilla.org/En/Core_JavaScript_1.5_Guide/Iterators_and_Generators
> 
> The Matrix has you.

Nice. Did you ever consider extending the matrix to DOM features? It
would mean a lot of extra effort, but it would make for a very useful
reference page. I'd be glad to help should you decide to do this.


  - Conrad
0
Conrad
6/6/2009 11:55:30 PM
Conrad Lender wrote:
> Thomas 'PointedEars' Lahn wrote:
>> I wonder why you think that `toSource' is even relevant.  First of
>> all, it is a proprietary JavaScript method (not defined in, but
>> allowed by ECMAScript) and secondly, it contains "[native code]" for
>> *all* native methods, with "native" meaning "not user-defined" here.
> 
> ad "first")
>   I was referring to Firefox in this case (I mentioned that).

I've seen that.  You haven't answered my question.

> ad "second")
>   Yes, that's what I meant. I'm not going to dig into the mess that is
> Firefox's source code now, but I'm pretty sure that Error is implemented
> in C++ instead of JavaScript.

So, as we know (or should know) that `Error' is an ECMAScript native object,
and do not assume that SpiderMonkey is written in JavaScript, why is the
return value of this proprietary method relevant *at all*?

>>>>> [StopIteration]
>>>> What is the purpose of this object?
>>> It's used with Iterators to signal a 'stop' condition: 
>>> https://developer.mozilla.org/En/Core_JavaScript_1.5_Guide/Iterators_and_Generators
>> The Matrix has you.
> 
> Nice. Did you ever consider extending the matrix to DOM features?

Yes, I did.  I can upload a preliminary version of the DOM Support Matrix if
you are interested.

> It would mean a lot of extra effort, but it would make for a very useful
> reference page. I'd be glad to help should you decide to do this.

Duly noted.


PointedEars
0
Thomas
6/7/2009 12:12:56 AM
On 07/06/09 02:12, Thomas 'PointedEars' Lahn wrote:
> Conrad Lender wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> I wonder why you think that `toSource' is even relevant.

I don't want to argue about this any more. I have the feeling we both
mean the same thing anyway, and are only quibbling about semantics.
What's more important:

>>> The Matrix has you.
>> 
>> Nice. Did you ever consider extending the matrix to DOM features?
> 
> Yes, I did.  I can upload a preliminary version of the DOM Support
> Matrix if you are interested.

I'm very interested.

>> It would mean a lot of extra effort, but it would make for a very
>> useful reference page. I'd be glad to help should you decide to do
>> this.
> 
> Duly noted.

If you'd like to delegate some of the work, you can contact me per
email; just replace 'yahoo' with 'gmail' (I only check the Yahoo account
about once a month). I also read the group (obviously ;-), in case you
want to organize this here.


  - Conrad
0
Conrad
6/7/2009 12:39:16 AM
Reply: