Sasha
Sasha

Reputation: 5944

typeof function is not a function

Colleague showed me the next code, which blown my mind:

const x = Object.create(function() {});
// variant: const x = Object.create(Array);
console.log(x.call) // ƒ call() { [native code] }
console.log(typeof x.call) // "function"
console.log(x.call instanceof Function) // true
x.call() // Uncaught TypeError: x.call is not a function

I understand that x.call is prototyped from function, it's not own x's property:

x.hasOwnProperty('call') // false

But why x.call can't actually being executed? Is it something related to call keyword?

Upvotes: 4

Views: 2677

Answers (2)

ibrahim tanyalcin
ibrahim tanyalcin

Reputation: 6491

The core idea behind Object.create boils down to this:

function create(prt){
    var noOP = function(){};
    noOP.prototype = prt;
    return new noOP;
}

So, the returned value is NOT a function, it is an object. To illustrate, I'll first store a function:

var u = function(){return 5}

Now I'll use Object.create on it:

var res = create(u);

Consoling it will give you >noOP {}, so it is a plain object. The problem starts from here:

res.hasOwnProperty("prototype") //false

So the newly created object has "prototype" but this is in fact inherited from u:

res.prototype === u.prototype //true

Similary, "call" is again inherited from u which in turn u inherits from its constructor's (Function) prototype:

res.call === u.call //true
res.call === Function.prototype.call //also true

And here is your problem, if you look at the EcmaScript implementation of call, it expects a this and this should be callable. Isolate call from res :

var x = res.call; //ƒ call() { [native code] }

Now I will "call" the call, we will pass 3 arguments, 1st for what to call, 2nd for setting this inside that callable, 3rd and so forth for arguments for the callable:

x.call(function(a){console.log("hey");console.log(a);console.log(this);},5,5)
//hey
//5
//Number {5}

Now try the same on your created object res either by res.call or x.call:

x.call(res,5,5) //TypeError: x.call is not a function

In the end, it boils down to returned object from Object.create not being callable.

Upvotes: 4

Jonas Wilms
Jonas Wilms

Reputation: 138267

Cause x is an object that inherits call from Function.prototype, however call is meant to be called on a function, therefore it fails if you try to execute it on a plain object.

Upvotes: 3

Related Questions