TypeError: X.prototype.y called on incompatible type

JavaScript 异常“在不兼容的目标(或对象)上调用”发生在当一个函数(在一个给定对象上)被调用时,其 this 不符合函数预期的类型。

消息

TypeError: Method Set.prototype.add called on incompatible receiver undefined (V8-based)
TypeError: Bind must be called on a function (V8-based)
TypeError: Illegal invocation (V8-based)
TypeError: Function.prototype.toString requires that 'this' be a Function (V8-based)
TypeError: this is not a Date object. (V8-based)
TypeError: this is not a typed array. (V8-based)
TypeError: Function.prototype.toString called on incompatible object (Firefox)
TypeError: Function.prototype.bind called on incompatible target (Firefox)
TypeError: 'addEventListener' called on an object that does not implement interface EventTarget. (Firefox)
TypeError: Type error (Safari)
TypeError: undefined is not an object (Safari)

错误类型

TypeError

哪里出错了?

当抛出此错误时,一个函数(在一个给定对象上)被调用时,其 this 不符合函数预期的类型。

当使用 Function.prototype.call()Function.prototype.apply() 方法时,并提供了不具有预期类型的 this 参数时,可能会出现此问题。

当将作为对象属性存储的函数作为参数传递给另一个函数时,也可能发生此问题。在这种情况下,当该函数被另一个函数调用时,存储该函数的对象将不会是该函数的 this 目标。为了解决此问题,您需要将回调函数包装在另一个函数中,或者使用 Function.prototype.bind() 方法强制将 this 参数绑定到预期对象。

示例

无效案例

js
const mySet = new Set();
["bar", "baz"].forEach(mySet.add);
// mySet.add is a function, but "mySet" is not captured as this.

function myFun() {
  console.log(this);
}
["bar", "baz"].forEach(myFun.bind);
// myFun.bind is a function, but "myFun" is not captured as this.

有效情况

js
const mySet = new Set();
["bar", "baz"].forEach(mySet.add.bind(mySet));
// This works due to binding "mySet" as this.

function myFun() {
  console.log(this);
}
["bar", "baz"].forEach((x) => myFun.bind(x));
// This works using the "bind" function. It creates a new function forwarding the argument.

另见