最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - typeof function is not a function - Stack Overflow

programmeradmin2浏览0评论

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

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?

Share Improve this question edited May 16, 2018 at 8:45 Sasha asked May 16, 2018 at 8:09 SashaSasha 5,9441 gold badge22 silver badges37 bronze badges 3
  • 6 Sometimes more exact error messages are useful, FF says: "TypeError: Function.prototype.call called on inpatible Object" – Teemu Commented May 16, 2018 at 8:11
  • Note that x has no function body. You can't call a function that doesn't have one. – Alnitak Commented May 16, 2018 at 8:25
  • 2 Also note that passing an instance of a type to Object.create doesn't produce the same result as passing the prototype of that type. You usually want to do the latter. – Alnitak Commented May 16, 2018 at 8:29
Add a ment  | 

2 Answers 2

Reset to default 4

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.

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.

发布评论

评论列表(0)

  1. 暂无评论