0

Is there any case where a Constructor returns something on purpose and it still makes sense to new it?

var Fn = function(){
    return this.fn = function(){}
}

var a = new Fn()
var b = Fn()

I can't seem to find any difference between a and b from console, but just in case I missed something, are they identical? Apart from b's side effect of adding fn as a method to window object. And if they're the same, does it mean that when a Constructor returns something, it's no longer a Constructor and shouldn't be newed?

Edit, the reason I'm asking is that I'm working with Coffee and Angular at the moment, while both seem to be pretty sensitive about return, especially with providers. Do you have any best practises regarding this?

Lucia
  • 13,033
  • 6
  • 44
  • 50
  • 2
    yes... else the property `fn` will be added to the `window` object - http://jsfiddle.net/arunpjohny/33o9a1js/1/ - with `new` there is no property added to window - http://jsfiddle.net/arunpjohny/33o9a1js/2/ – Arun P Johny Sep 24 '14 at 03:12
  • 1
    If a constructor returns something on purpose, it's not a constructor any more. – Bergi Sep 24 '14 at 18:25

2 Answers2

0

Yes. The new invocation creates a new this context in which the function inside the constructor will be evaluated. Without it, the invocation assumes the local context and attaches your function to it. This is really important if you have multiple functions that you want to bind a unique object to.

I had the same question you did, and read the spec. I wrote about this in What the 'new' operator means to Javascript.

Arun's answer is half-right, in that it's true for the special case that you're working at the base level of the Javascript interpreter, where this === windows (or, for Node, this === global; for PLv8, this === role). Inside other objects (a really common occurrence when working with modern libraries like jQuery or Backbone!), the this operator is the local context, not the windows root.

Elf Sternberg
  • 16,129
  • 6
  • 60
  • 68
0

So with the information @Elf provided, as in

When the [[Construct]] property for a Function object F is called, the following steps are taken:

  1. Create a new native ECMAScript object.
  2. Set the [[Class]] property of Result(1) to “Object”.
  3. Get the value of the prototype property of the F.
  4. If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
  5. If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.
  6. Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.
  7. If Type(Result(6)) is Object then return Result(6).
  8. Return Result(1).

When the Constructor intentionally returns something, that something would get returned in Result(6), therefore defying the purpose of Constructors--to return Result(1) as an instance.

The only possible use of this is to take advantage of Step 6 and call the Fn with certain arguments and certain this, which, could easily be done without using Constructors and a simple call. So I guess, if Constructors return stuff, it ain't Constructor anymore.

Edit:

The interesting exception being, the object returned is Result(1) on purpose, in order to be able to take arbitrary number of arguments: Use of .apply() with 'new' operator. Is this possible?. Thanks @Elf.

Community
  • 1
  • 1
Lucia
  • 13,033
  • 6
  • 44
  • 50
  • 1
    Yes and no. By exploiting and emulating this behavior, you can [Call a constructor using '.apply' and a variable number of arguments](http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible) which is useful in some circumstances, and is still a Constructor, it's just one you wrote yourself. – Elf Sternberg Sep 25 '14 at 15:17