首页 > 解决方案 > Javascript:typeof 表示“函数”,但不能作为函数调用

问题描述

这次我真的对 Javascript 感到困惑:

var x = Array.prototype.concat.call;
typeof x; // function
x(); // Uncaught TypeError: x is not a function

这到底是怎么回事?


如果有帮助,我还注意到:

在 Chrome 和 Node.js 中测试。

标签: javascriptfunctiontypeerror

解决方案


该错误具有误导性。x一个函数,但是它丢失了引用的函数(concat),这会引发错误

在 firefox 上运行会给出更具描述性的错误

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Called_on_incompatible_type

它的意思是该call函数没有任何约束。就像你拿一个像这样的对象一样:

const a = {
  b: 2,
  test() {
    console.log('hi', this.b);
  }
};
const c = a.test;
c();

hi undefined当你失去了函数与 b 的关系时,你会得到。

您可以通过执行c.bind(a)()c.call(a)

call函数的行为类似。每个函数都是一样的,伪代码看起来像这样:

class Function {
  constructor(functionDefinition) {
    this.functionDefinition = functionDefinition;
  }

  call(newThis, ...args) {
    // take this.functionDefinition, and call it with `this` and `args`
  }
}

由于您要提取调用函数,因此它会丢失与之关联的函数对象。

您可以通过将 concat 绑定到函数或使用 call on call 来解决此问题 :-)

const a = []
const boundFn = a.concat.call.bind(a.concat)
console.log(boundFn([3], [1,2]));

// Or, you can use `call` to pass in the concat function
const callFn = a.concat.call;
console.log(callFn.call(a.concat, [4], [1,2]))


推荐阅读