类型错误:X.prototype.y 调用了不兼容的类型

当使用与函数期望的类型不对应的 this 调用函数(在给定对象上)时,会发生 JavaScript 异常 "在不兼容的目标(或对象)上调用"。

¥The JavaScript exception "called on incompatible target (or object)" occurs when a function (on a given object), is called with a this not corresponding to the type expected by the function.

信息

¥Message

TypeError: Method Set.prototype.add called on incompatible receiver undefined (V8-based)
TypeError: Bind must be called on a function (V8-based)
TypeError: Function.prototype.toString called on incompatible object (Firefox)
TypeError: Function.prototype.bind called on incompatible target (Firefox)
TypeError: Type error (Safari)
TypeError: undefined is not an object (Safari)

错误类型

¥Error type

TypeError

什么地方出了错?

¥What went wrong?

引发此错误时,将使用与函数期望的类型不对应的 this 调用函数(在给定对象上)。

¥When this error is thrown, a function (on a given object), is called with a this not corresponding to the type expected by the function.

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

¥This issue can arise when using the Function.prototype.call() or Function.prototype.apply() methods, and providing a this argument which does not have the expected type.

当提供一个存储为对象属性的函数作为另一个函数的参数时,也可能会发生此问题。在这种情况下,当其他函数调用该函数时,存储该函数的对象将不会成为该函数的 this 目标。要解决此问题,你需要提供进行调用的 lambda,或者使用 Function.prototype.bind() 函数将 this 参数强制传递给预期对象。

¥This issue can also happen when providing a function that is stored as a property of an object as an argument to another function. In this case, the object that stores the function won't be the this target of that function when it is called by the other function. To work-around this issue, you will either need to provide a lambda which is making the call, or use the Function.prototype.bind() function to force the this argument to the expected object.

示例

¥Examples

无效案例

¥Invalid cases

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

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

有效案例

¥Valid cases

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

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

也可以看看