2

Both of the following constructor functions work the same (as far as I have been able to tell) when I invoke them as:

var x2z = new xyz('ralph');

whether I write a constructor function like this:

function xyz(name) {
    return {
        name: name,
        x:1,
        get y() {return this.x+1},
        get z() {return this.y+1}
    }
}

or if I had declared it:

function xyz(name) {
    this.name = name;
    this.x = 1;
    Object.defineProperties(this, {
        "y": {"get": function() {return this.x+1}}
    }),
    Object.defineProperties(this, {
        "z": {"get": function() {return this.y+1}}
    })
}

The second form is the one that is documented everywhere. But why does the first one work? Is the new keyword just ignored and the object literal returned?

How are the two related to one another? If someone could point me to a reference that would be great; I can find a lot of stuff on objects but I haven't found anything on the first form.

I put together a simple jsperf and the literal version is slightly faster, but not enough to use it if it's just an oddity. (jsperf example). But it seems more straightforward than the more typically used constructor that refers to "this".

bmacnaughton
  • 4,950
  • 3
  • 27
  • 36
  • I use the former all the time. It works because doing `new xyz` creates a closure over the returned object. This means every local property available on the time of creation of the returned object (e.g: `this`) is available to the returned object even after the object is returned. – Geert-Jan Nov 18 '14 at 19:53

2 Answers2

2

MDN has very nice documentation about "new": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new

The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created [initially] is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)

Arseny Smoogly
  • 600
  • 2
  • 7
1

why does the first one work?

Notice that the first one does not create instances which inherit from xyz.prototype.

Is the new keyword just ignored and the object literal returned?

Yes. If the constructor returns an object, that will be returned by the new operator instead of the instance that was constructed and passed to the constructor as this. For details, see What is the 'new' keyword in JavaScript? or MDN.

However, notice that if you use the first, you should omit the new (to make clear it's a factory function), and if you use the second you should capitalize your constructor to Xyz.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks for these useful observations. Another difference is that returning the object literal results in `obj instanceof xyz` being false. If `xyz` uses `this` instead of returning an object literal the `instanceof` operator is true. – bmacnaughton Nov 20 '14 at 14:41
  • Well, that `instanceof` thing is *because* the returned object does not inherit from `xyz.prototype`… – Bergi Nov 20 '14 at 17:57