Method Set.prototype.已调用不兼容的接收器未定义



在使用JavaScript多年后,我遇到了一个我从未见过的错误。

我想计算两个集合之间的交集,所以我写了:

let a = new Set([1, 2, 3]);
let b = new Set([2, 3, 4]);
let intersection = [...a].filter(x => b.has(x));
console.log(intersection);

它可以工作,但我注意到我可以缩短上面的代码。由于过滤器方法只需要一个函数并调用它,无论它是如何定义的,我写道:

let a = new Set([1, 2, 3]);
let b = new Set([2, 3, 4]);
let intersection = [...a].filter(b.has);
console.log(intersection);

在这种情况下,出乎意料的是,我收到以下错误:

未捕获的类型错误:方法 Set.prototype.已调用不兼容的接收器未定义

我还注意到,如果我将Set.prototype.add绑定到变量,就不会发生这种情况:

let a = new Set([1, 2, 3]);
let b = new Set([2, 3, 4]);
let intersection = [...a].filter(Set.prototype.bind(b));
console.log(intersection);

我的问题是:为什么会发生这种情况?为什么b.has不是有效的回调?

当您将其作为回调传递时,has方法会丢失内部this上下文。

这就是当您使用bind为其提供正确的上下文时它起作用的原因。

有关更多信息,已在此处记录

您可以使用Array#filter函数并将thisArg作为第二个参数传递。因此,has将把这第二个参数作为this,并继续计算或比较。

下面是一个示例:

function compare(a, b) {
return [...a].filter(Set.prototype.has, b);
}
let a = new Set([1, 2, 3]);
let b = new Set([2, 3, 4]);
console.log(compare(a, b));

另一个想法:

function compare(a, b) {
return new Set([...a].filter(Set.prototype.has, b));
}
let a = new Set([1, 2, 3]);
let b = new Set([2, 3, 4]);
console.log([...compare(a, b).values()]);

最新更新