`new Object` vs `Object` difference

# Benjamin Gruenaum (9 years ago)

Ok, so I gave this a few hours in the open.

So, I'm looking at the ES5 specification (also checked the current ES draft which is similar) at the definition of what new Object and Object do. To my surprise:

  • new Object describes a whole algorithm of how the object constructor works - treating what happens with different kinds of values. Basically calls ToObject on non objects - identity on objects and builds on null and undefined.
  • Object has a special first step for null and undefined where it builds an object and then calls ToObject on primitives and identity on objects.

After reading the description a few times - they seem identical. However, clearly from the spec they do something different. For example in Array - calling new Array is specified as the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.`

The only difference I've been able to identify with the help of a friend is that the behaviour can be different on host objects. Where Object must return the same host object and new Object may return the same host object.

I've taken a look at the ES3 specification and it too uses the same definition so I suspect this is something that has been there for a long time.

  • Why are Object and new Object specified differently?
  • If there is no actual reason, can the definition be simplified for the next version of the spec? (I think simplifying the spec is important and possibly underrated)

Sorry if I'm missing something obvious.

Originally asked on Stack Overflow - stackoverflow.com/q/30801497/1348195

# Andrea Giammarchi (9 years ago)

I think historically Array, Function, and Object can be used with or without new and the result is exactly the same ... since, about, ever.

Agreed if that's actually indeed the case, we could have just one definition for those 3 constructors (not just Object)

# Benjamin Gruenaum (9 years ago)

Thanks, Array and Function (as well as RegExp) actually directly specify that calling them with and without new produces equivalent results where Object doesn't and actually has a hole (in what it may do to host objects).

It's just baffling that Object is defined so differently. I wonder if there are old browsers that differ on this, or there is a bigger reason for this behaviour.

# Andrea Giammarchi (9 years ago)

Yep, RegExp too, you are right. The only caveat that might comes to my mind is dealing with foreigner objects ( through plugins such Java applets and stuff ) where maybe there is a difference, but I've no memory of any sort of real-world use case based on the fact that new was mandatory.

Indeed if you try even minifiers, you'll notice that code like this

this.bla = new Object(parent.foreignObject);

will be minified as

this.bla=Object(parent.foreignObject);
# Allen Wirfs-Brock (9 years ago)

ES6 eliminates the (possible) special treatment of host objects passed as the argument to the Object constructor. As far as anybody seems to know, no implementation had ever made use of that allowance.

The ES6 spec. also unifies the [[Call]] and [[Constructor]] behavior of Object into a single algorithm people.mozilla.org/~jorendorff/es6-draft.html#sec-object-value ES6 unifies all [[Call]] and [[Construct]] algorithms for built-in constructors in this same manner.

# Benjamin Gruenaum (9 years ago)

That's good to know and it's good to know I'm not the first one to spot this.

While we're visiting the spec on that:

Why is it specified that "When called as a constructor it creates a new ordinary object. When Object is called as a function rather than as a constructor, it performs a type conversion." - wouldn't it make more sense to remove that or specify "behaves the same way"?

Where is it actually explained what Object does when called as a constructor?

The difference - at least in the phrasing of Object vs Array seems to be just as present in the latest spec draft from what I can tell.

# Allen Wirfs-Brock (9 years ago)

On Jun 12, 2015, at 2:47 PM, Benjamin Gruenaum wrote:

That's good to know and it's good to know I'm not the first one to spot this.

While we're visiting the spec on that:

Why is it specified that "When called as a constructor it creates a new ordinary object. When Object is called as a function rather than as a constructor, it performs a type conversion." - wouldn't it make more sense to remove that or specify "behaves the same way"?

yes, probably

Where is it actually explained what Object does when called as a constructor?

It doesn't because the behavior is seem in both cases.

Step 1 of people.mozilla.org/~jorendorff/es6-draft.html#sec-object-value is looking for the case of a super() call from a subclass constructor.

The difference - at least in the phrasing of Object vs Array seems to be just as present in the latest spec draft from what I can tell.

Yes, the Object description still contains some ancient language that should probably be removed in the future as it adds not (except perhaps confusion) to the spec.

# Bucaran (9 years ago)

JS is very much like writing with a pen (traditionally speaking). We can only try to make less errors as we move forward, but what’s there it’s there and it’s either too expensive or impossible to change.

# Benjamin Gruenbaum (9 years ago)

Pointing out that I'm replying to a message with an empty subject - using the correct original title here

---------- Forwarded message ---------- From: Rock <zloirock at zloirock.ru>

Benjamin Gruenaum, Andrea Giammarchi, you are wrong about RegExp:

var re = /./;
new RegExp(re) === re; // false
RegExp(re) === re; // true

Nice catch. This is states explicitly as a difference to the rule here
http://es5.github.io/#x15.10.3.1

> If pattern is an object R whose [[Class]] internal property is "RegExp"

and flags is undefined, then return R unchanged. Otherwise call the
standard built-in RegExp constructor (15.10.4.1) as if by the expression
new RegExp( pattern, flags) and return the object constructed by that
constructor.

I didn't notice that - thanks.