X is not a function ... what would you expect from Object.create with a constructor

On this issue, I do not expect a solution to solve something, but I would like to better understand the situation.

Some quotes from the specification:

  • 5.1 Edition ( Link )

    ยง15.2.3.5 Object.create (O [, Properties])

    The create function creates a new object with the specified prototype. When the create function is called, the following steps are performed:

    • If Type (O) is not Object or Null, throw a TypeError exception.
    • Let obj be the result of creating a new object, as if the expression new Object (), where Object is the standard built-in constructor with this name
    • Set the internal [[Prototype]] property of the obj object to O.
    • If the Properties argument is present rather than undefined, add your own properties to obj, as if it had called the standard built-in function Object.defineProperties with the arguments obj and Properties.
    • Return obj.
  • Edition 6 - draft ( Link )

    ยง19.1.3.2 Object.create (O [, Properties])

    The create function creates a new object with the specified prototype. When the create function is called, the following steps are performed:

    • If Type (O) is not Object or Null, throws a TypeError exception.
      • Let obj be the result of an abstract ObjectCreate operation with argument O.
      • If the Properties argument is present, not undefined, then a. Returns the result of the abstract operation ObjectDefineProperties (obj, Properties).
      • Return obj.

If I understood correctly, both specifications allow the following code to be executed:

function F() { } var x=Object.create(F); // a minimal test alert(x.prototype.constructor===F); // true alert(x instanceof Function) // true alert(typeof x) // 'object' 

It seems he created an object of the type derived from (sorry for the bad terminology ..) Function , as I tested in FireFox, and therefore x not invocable :

 x(); // x is not a function 

I think about why it does not prohibit the constructor to be used as O , or just create a valid constructor.

So, I wonder what you expect from Object.create with a constructor?

+7
javascript
source share
2 answers

Unfortunately this will not work. You have an object with F in the prototype chain; the fact that F is a function does not make the function x .

Only objects created by declaring a function or function expression will have a โ€œFunctionโ€ as their [[Class]] and [[Call]] method, which makes it callable. They are created in accordance with the steps described in the section in section 13.2 of the ECMAScript 5 specification .

The algorithm for Object.create does something else, as you can see in your quote. In your case, x will be an ordinary object with [[Class]] "Object" and no [[Call]]. If you try Object.prototype.toString.call(x) , you will get "[object Object]" , where "Object" is [[Class]] in x . x instanceof Function returns true only because the Function constructor is part of the x prototype chain (via F ).

I'm not sure if any of these will be changed in ES6, but I believe that this will not happen.

+4
source share

So, I wonder what you expect from Object.create with a constructor?

I would expect it to follow the specification, of course ...

I think about why it does not prohibit the constructor to be used as O

Why? Each constructor function is an object (ยง8.6) .

... or just create a valid constructor.

The spectrum says that it should create a simple object (for example, new Object ) whose [[prototype]] is set to O. Ordinary objects are not functions, they do not have [[call]] or [[construct]]. It will also have a [[class]] Object , not a Function .

 x.prototype.constructor===F // true x instanceof Function // true typeof x // 'object' 

It seems that he created an object of the type that comes from (sorry for the bad terminology ..) Function

From F , actually. It inherits the .prototype property from F (so your first test is true ), and through F it also inherits from Function.prototype , which makes it instanceof Function . However, it does not have the [[call]] property (it cannot be called), so typeof does not give "function" , but simply "object" .

+2
source share

All Articles