user137364
user137364

Reputation: 305

Number vs new Number internal implementation

I understand that writing

var x = Number("7"); // makes a number, a primitive
var y = new Number("7"); // makes a Number object

and I'm aware of the usual cautions against option 2, but what is going on behind the scenes? I was under the impression if a function is a constructor, it should not return a value via a return statement: it just sets up its implicit object, this, and returns it.

So how come Number, String, and Boolean constructors are able to return either a primitive or an object? Does the JavaScript engine parse those expressions differently as a special feature in the language? Or can a programmer also "overload" a constructor function to either return a primitive or an object, depending on whether the constructor is called with/without "new"?

Upvotes: 2

Views: 55

Answers (2)

Ele
Ele

Reputation: 33726

Using the constructor the Number object will be an object, using the function Number instead will return the conversion of an object to its representation as a numeric value.

So, basically within the Number object, the function is validating how was called. This is possible by checking the object this.

Something interesting is coercing the Number object to a numeric value as follow:

var x = Number("7"); // makes a number, a primitive
var y = new Number("7");

console.log(x === +y)

Go and read about the specification

https://www.ecma-international.org/ecma-262/5.1/#sec-15.7

enter image description here

Upvotes: 2

Pointy
Pointy

Reputation: 413826

It has nothing to do with syntax and there's nothing special about those constructors. The Number() and other constructors simply test to see whether this is bound before proceeding.

You can do it too:

function MyConstructor() {
  if (!this) return new MyConstructor();
  // stuff ...
}

Now calling MyConstructor() will behave exactly like new MyConstructor().

Also, a constructor can return something. If it returns an object, then that's used instead of the implicitly-constructed object that new creates. Thus you could also implement a "new-is-optional" constructor another way:

function MyConstructor() {
  let object = this || Object.create(MyConstructor.prototype);
  // stuff ...
  return object;
}

So the Number() constructor takes a different tack. In most runtimes it may or may not actually be implemented as JavaScript, but if it were it might look something like this:

function Number(n) {
  if (this) {
    // invoked with "new"
    this.fantasyValueSetter(n); // cannot really do this
    return this;
  }
  return +n; // plain number primitive if not invoked with "new"
}

Upvotes: 1

Related Questions