这次我真的对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和节点中测试。
答案 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]))