在不兼容的接收器上调用了方法Set.prototype.undefined

时间:2018-08-14 21:20:20

标签: javascript

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

我想计算两个 Set 之间的交点,所以我写道:

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);

它有效,但是我注意到我可以缩短上面的代码。由于filter方法只需要一个函数并调用它,而不管其定义如何,所以我写道:

let a = new Set([1, 2, 3]);
let b = new Set([2, 3, 4]);

let intersection = [...a].filter(b.has);

console.log(intersection);

在这种情况下,我意外地收到以下错误:

  

未捕获的TypeError:未定义不兼容的接收器上调用了方法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不是有效的回调?

2 个答案:

答案 0 :(得分:2)

has方法在作为回调传递时会丢失内部this上下文。

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

有关更多信息,请参见here

答案 1 :(得分:1)

您可以使用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()]);