2

Is it possible to do new new A in JS with A !== Function? What's the desired structure of A then?

3
  • Did you mean new A instead? Commented Aug 13, 2014 at 13:06
  • possible duplicate of What is the 'new' keyword in JavaScript? Commented Aug 13, 2014 at 13:07
  • I'm aware what the new keyword is. Thank you. Commented Aug 13, 2014 at 13:12

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Excellent! That's the answer I've been expecting. Is it a standard-compliant behaviour?
@polkovnikov.ph Yes, this is perfectly valid ECMAScript behavior per the [[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.
@torazaburo Don't you have an idea on how to restore a prototype chain there?
@polkovnikov.ph 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).
@apsillers I forgot why on earth did I need it myself, but then remembered that I'd like to var User = new Model(...), user = new User(...);.
0

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

This is little more than a curiosity, but: the spec does not disallow non-function host objects from implementing an internal [[Construct]] property, though I don't know of any actual host environment that supplies non-function constructors.
Should 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]]?
@polkovnikov.ph It is not possible to directly alter an object's internal properties from JS code, which is part of the reason why they're called "internal". To answer your first question: A must be a function and the result of new A must also be a function.
Both 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.
@joews Note that question specifies 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.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.