Is it possible to do new new A in JS with A !== Function? What's the desired structure of A then?
2 Answers
Yes, in theory.
function A() {
return function B() {
}
}
> new new A
B {}
or
> new new A()
> new new A() ()
since the parentheses are optional with the new operator.
This takes advantage of the fact that a constructor may return something other than the constructed object. It is extremely unclear why anyone would ever want to do this. Also, this does not change the fact that new can only be invoked on a function.
Dept. of Curiosities
This
function A() { return A; }
allows you to do this
new new new new new new new new new new new new A
which there is no point whatsoever in doing.
Prototype Chains
You know that calling new on a constructor constructs an object with the prototype for that constructor. However, if you return any object other than this from a constructor, this, along with its associated prototype, is forever lost to the world. Whatever object you return has its own prototype, coming from wherever--not that of A. This applies equally to the case here where the constructor returns a function, in which case the relevant prototype is Function.prototype. Is there any way to arrange it, in the unlikely event that we cared, so that new A continues to return a functioning function, which we can do a new on, while also having access to A.prototype?
Not easily. If you want additional properties on the function B returned from new A, then you can just add those properties before returning function B.
5 Comments
[[Construct]] specifiction: Let result be the result of calling the [[Call]] internal property... If Type(result) is Object then return result. (i.e., if the function's behavior when called returns an object, use that object as the return value of the constructing new call). Functions are objects, so it's a valid return value for a constructor.A is a function that constructs a constructor (we'll call this constructed constructor B). When you construct an instance of B, the instance uses B's prototype chain. Simply build your prototype chain around B in instead of A -- A is a constructor that makes constructors, not proper objects. If using B.prototype is not practical for some reason (you haven't said why on earth you need to support new new A), you can also have B return an object created with Object.create(A.prototype).var User = new Model(...), user = new User(...);.No, it's not possible. A must be a function, regardless of its return value.
Source: ECMAScript 5 spec for the new operator:
If constructor does not implement the [[Construct]] internal method, throw a TypeError exception.
From the Function specification, we can see that [[Construct]] is a special internal (inaccessible) property of Function objects.
6 Comments
[[Construct]] property, though I don't know of any actual host environment that supplies non-function constructors.A be a function or new A be a function? Why is it impossible to tweak a constructor of a type so that constructed objects would have an internal [[Construct]]?A must be a function and the result of new A must also be a function.A and (new A) must be functions or, as apsillers points out, special (probably non-existent) objects that the runtime endows with a [[Construct]] property. [[Construct]] is purely in the realm of the host runtime; the executed JavaScript code cannot touch it.A !== Function not typeof A != "function" (that is, A could be a function, just not the particular Function constructor function), so it is technically possible, per torazaburo's answer.
new Ainstead?newkeyword is. Thank you.