Javascript:typeof说"功能"但它不能被称为功能

时间:2018-05-19 01:57:28

标签: javascript function typeerror

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

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

这到底是怎么回事?

如果有帮助,我也注意到了:

  • x([1,2],[3,4])不起作用

  • toString也认为它是一个功能:

    Object.prototype.toString.call(x); // "[object Function]"
    
  • 这也适用于Array.prototype.concat.apply

  • 当它被强制表达时,它也不起作用:

    (0, Array.prototype.concat.call)([1,2],[3,4]); // Same TypeError
    

在Chrome和节点中测试。

1 个答案:

答案 0 :(得分:7)

该错误具有误导性。 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]))