Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`new Object` vs `Object` in the ECMAScript spec

So, I'm looking at the ES5 specification 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.`

So - what is the difference between new Object and Object? Why were they specified differently?

For ease - here's a link to the spec.

like image 918
Benjamin Gruenbaum Avatar asked Jun 12 '15 11:06

Benjamin Gruenbaum


People also ask

What is new object in JavaScript?

The new keyword is used in javascript to create a object from a constructor function. The new keyword has to be placed before the constructor function call and will do the following things: Creates a new object. Sets the prototype of this object to the constructor function's prototype property.

What is the difference between object and object in JavaScript?

Javascript is case sensitive "object" is essentially a variable that can hold anything. "Object" is an actual javascript type.

What is the difference between object create and new in JavaScript?

The object used in Object. create() actually forms the prototype of the new object, whereas in the new Function() from the declared properties/functions do not form the prototype. You cannot create closures with the Object.

Is an object or class or objects defined by ECMAScript?

A native object is an object or class of objects defined by the ECMAScript specification. Arrays, functions, dates, and regular expressions (for example) are native objects.


1 Answers

Object(window) will never clone window but new Object(window) might. All current -- potentially all known -- implementations just return the same reference, although the spec allows for implementation-defined behavior.

The steps for 15.2.1.1 say:

  1. If value is null, undefined or not supplied, create and return a new Object object exactly as if the standard built-in Object constructor had been called with the same arguments
  2. Return ToObject(value).

The definition of ToObject (9.9) lists a few types that will be caught by step 1 (in table 14), but for Object has a very simple definition:

The result is the input argument (no conversion).

It explicitly states that the input argument will be returned as-is, so they should be equal references (===).

The definition for new Object (15.2.2.1) has a similar chain of type-checks in step 1, but the step for objects (1.a) is:

i. If the value is a native ECMAScript object, do not create a new object but simply return value.

ii. If the value is a host object, then actions are taken and a result is returned in an implementation-dependent manner that may depend on the host object.

That is, for any host object foo, the call Object(foo) must === foo but new Object(foo) may === foo.

Host objects are defined in 4.3.8 to be

object supplied by the host environment to complete the execution environment of ECMAScript.

This answer lists a few host objects to include window, history, etc. Running those through new Object(foo) should (but doesn't have to) return a different object.

In any case but passing a host object, new Object(foo) seems to be a more complicated chain that defers to ToObject in much the same way as Object(foo).

Unfortunately, 15.2.2.1.1.a.ii states that the "result is returned in an implementation-dependent manner" and has no specifics as to the "actions [that] are taken" and it appears that Chrome will return the same object (equal references) for all of the listed "host objects."

Using this script to check:

var objects = [
  /* Native objects */
  'Object', 'Date', 'Math', 'parseInt', 'eval',
  /* Host objects */
  'window', 'document', 'location', 'history', 'XMLHttpRequest', 'setTimeout'
];

function getDefinedReference(name) {
  if (eval('typeof ' + name) !== 'undefined') {
    return eval(name);
  } else {
    throw new Error('' + name + ' is not defined.');
  }
}

function checkIdentity(name) {
  try {
    var ref = getDefinedReference(name);
    var no = new Object(ref);
    var o = Object(ref);

    console.log(name, ref === no, ref === o, no === o);

    if (ref === o && no !== o) {
      // Make sure ref === Object(ref) but not new Object(ref)
      console.log(name, 'returns different references.');
    }
  } catch (e) {
    console.warn(e);
  }
}

objects.forEach(checkIdentity);

if (typeof window !== 'undefined') {
  for (var f in window) {
    checkIdentity(f);
  }
}

doesn't find any objects where Object and new Object behave differently. @Xotic750 seems to be right that it can be implementation-dependent, but nobody is using it.

like image 114
ssube Avatar answered Sep 23 '22 05:09

ssube