TL;DR
There is no difference between new Object(realthing) and Object(realthing). They do the same thing.
Much longer answer
When it comes to JS, reading the spec is always a good idea, although it can be incredibly hard to figure out what things mean. So, let's dive into this: in this case, we want the rules for how Object() works:
19.1.1The Object Constructor
The Object constructor:
- is the intrinsic object %Object%.
- is the initial value of the Object property of the global object.
- creates a new ordinary object when called as a constructor.
- performs a type conversion when called as a function rather than as a constructor.
- is designed to be subclassable. It may be used as the value of an extends clause of a class definition.
So we have two cases to look at: Object(sym), and new Object(sym).
What happens for Object(sym)?
19.1.1.1 Object([ value ])
When the Object function is called with optional argument value, the following steps are taken:
- If NewTarget is neither undefined nor the active function, then
Return ? OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%").
- If value is null, undefined or not supplied, return ObjectCreate(%ObjectPrototype%).
- Return ! ToObject(value).
(Note that ? and ! here are not "code", they are spec syntax. ! means "this operation will always return a normal value whereas ? may return an abnormal value)
In this case, we didn't use new, so step 1 doesn't apply. The value is not nullish, so step 2 doesn't apply, and we end up executing step 3: we perform a type conversion so we end up with a new object for which typeof will now say "object", no matter what it was before, but with the original data preserved as value.
What happens for new Object(sym)?
Looking at 19.1.1.1 again, we're using new this time, so we might expect step 1 to kick in: after all, there is a NewTarget (by definition: we used new so there is a NewTarget), but it turns out the NewTarget is the Object function itself, making NewTarget the active function, and so step 1a does not kick in.
We also have a value, and it's not nullish, so step 2 doesn't kick in, and we again run step 3: type conversion.
So Object(sym) and new Object(sym) do exactly the same thing, just for subtly different reasons.
So how does ToObject work?
Looking at the spec again:
7.1.13ToObject ( argument )
The abstract operation ToObject converts argument to a value of type Object according to Table 12:
Undefined Throw a TypeError exception.
Null Throw a TypeError exception.
Boolean Return a new Boolean object whose [[BooleanData]] internal slot is set to argument. See 19.3 for a description of Boolean objects.
Number Return a new Number object whose [[NumberData]] internal slot is set to argument. See 20.1 for a description of Number objects.
String Return a new String object whose [[StringData]] internal slot is set to argument. See 21.1 for a description of String objects.
Symbol Return a new Symbol object whose [[SymbolData]] internal slot is set to argument. See 19.4 for a description of Symbol objects.
Object Return argument.
So the first observation should be that "if it's an object, ToObject does nothing". That's of course not the case for your Object(sym), so what happens for it?
A new object gets built, with its type set to object (irrespective of what the input value type is), and this new object's prototype will be set to match whatever the input value's prototype was. Then the new object's internal value literally gets copied over from the input value that's getting converted.
But we're not quite done
typeof is useless for testing "what a thing is".
Remember that almost everything in JS is an object, and typeof will only tells you the basic type of something. As such, there are only six answers it can give you:
- object
- function
- string
- symbol
- number
- undefined
That's it. The typeof operator tells you nothing about the what the most specific type is, instead it tells you what the most generic type is.
For the specific type, either use thing.constructor.name to find out which constructor function actually got used to build the thing you're examining, or use thing.__proto__ to get a reference to that type. Or, if you have the type already and merely need to test to see if "thing is a ...", use the instanceof operator:
> typeof 3
"number"
> typeof Object(3)
"object"
> Object(3).constructor.name
"Number"
> Object(3).__proto__
Number { 0 }
> Object(3) instanceof Number
true