5

I'm reviewing ECMAScript 5.1 Specification kinda seriously.

And I'm curious if there is a way to tell what the "real constructor function" of an object in ES5. ( not the explicit "constructor" property )

According to the spec, explicit "constructor" property is just a initial back-reference from the byproduct object of a function object to the function object.

(Here, the byproduct is the object which is initially pointed by the function object's explicit "prototype" property.)

So, explicit "constructor" property has nothing to do with the real constructor of an object:

function Foo(name){ this.name = name; }
var foo = new Foo("Brian");
var bar = { a: 10, b: function(){ if(this.name) return this.name; }};
Foo.prototype = bar;
var foo2 = new Foo("John");   // Let me call Foo as "real constructor" of foo2

Here, even though foo2 was created by Foo, since Foo.prototype was pointing to bar at the moment of creation of foo2, so foo2's internal [[Prototype]] gets to point to bar, and we can check this by:

Object.getPrototypeOf(foo2) === bar   // true

Since foo2 doesn't have own "constructor" property as usual, so, reading foo2.constructor is actually [[Prototype]] chain lookup, that is, foo2.constructor --> (( foo2.[[Prototype]] )).constructor --> bar.constructor which is Object, not Foo.

You can check this by:

foo2.constructor === Foo         // false
foo2.constructor === Object      // true

Finally, is there no way to find Foo from the object foo2?

ADD: I'm talking about ES5. Please do not bring anything engine-dependent or ES6-thingy (e.g. __proto__ )

2
  • 2
    Well I'm going to go out on a limb here and say that it is not possible. As far as I know, there is nothing that solidly links the constructor function with the constructed object. You can change Foo.prototype after you created the object and even foo2 instanceof Foo will not work anymore. Just think of the constructor function as a blue print. You use it to create an object but after you created it, there is nothing that prevents you of doing totally different things to both of them. Commented Oct 7, 2015 at 17:19
  • also, don't forget that it's perfectly possible for a constructor to return an entirely new object instead of the implicit return this, in which case there is absolutely no link back to the function that created it. Commented Oct 7, 2015 at 17:53

1 Answer 1

4

No, the language does not natively offer any feature that does this.

If we consult the spec on the new operator, we see it is largely a call to a function's [[Construct]] internal method. Turning our attention to [[Construct]], we see:

When the [[Construct]] internal method for a Function object F is called with a possibly empty list of arguments, the following steps are taken:

  1. Let obj be a newly created native ECMAScript object.
  2. Set all the internal methods of obj as specified in 8.12.
  3. Set the [[Class]] internal property of obj to "Object".
  4. Set the [[Extensible]] internal property of obj to true.
  5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
  6. If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
  7. If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
  8. Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
  9. If Type(result) is Object then return result.
  10. Return obj.

As you can see in steps 5 through 7, the only handling of the object created by new does by the environment is to set its [[Prototype]] and then hand it off to the function's [[Call]] method for processing in step 8. If the value assigned to the object's [[Prtototype]] does not contain an accurate constructor property, there is no way to know what constructor function created an object.

You could, of course, store that information in your own constructor code by setting a value on the object at creation-time, but the JavaScript engine will not do it for you.

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

1 Comment

Okay, now it seems clear again. Actually, I was curious when the Chrome console spit out the real constructor correctly for the above example. So, it must be engine's internal implementation that is not exposed to public.

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.