简体   繁体   English

typeof函数不是函数

[英]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.call是从function原型创建的,它不是x的属性:

x.hasOwnProperty('call') // false

But why x.call can't actually being executed? 但是,为什么x.call不能实际执行? Is it something related to call keyword ? call关键字有关吗?

原因x是一个继承自Function.prototype call的对象,但是call是要在函数上调用的,因此,如果您尝试在一个普通对象上执行它,则它将失败。

The core idea behind Object.create boils down to this: Object.create背后的核心思想可以归结为:

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: 现在,我将在其上使用Object.create

var res = create(u);

Consoling it will give you >noOP {} , so it is a plain object. >noOP {}它会给你>noOP {} ,所以它是一个普通的对象。 The problem starts from here: 问题从这里开始:

res.hasOwnProperty("prototype") //false

So the newly created object has "prototype" but this is in fact inherited from u : 因此,新创建的对象具有“原型”,但实际上这是从u继承的:

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

Similary, "call" is again inherited from u which in turn u inherits from its constructor's (Function) prototype: 类似地,“ call”再次从u继承,而u又从其构造函数的(Function)原型继承:

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. 这就是您的问题,如果您看一下call的EcmaScript实现,它期望this并且this应该是可调用的。 Isolate call from res : res隔离call

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: 现在,我将“调用”该调用,我们将传递3个参数,第一个用于调用,第二个用于在可调用对象中设置this参数,第三个用于可调用对象的参数,依此类推:

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 : 现在,通过res.callx.call在创建的对象res上尝试相同的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. 最后,它归结为无法调用的Object.create返回的对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM