在使用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()]);