After years of using JavaScript I met an error that I had never seen.
I wanted to calculate the intersection between two Sets, so I wrote:
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);
And it works, but I noticed that I can shorten the above code. Since the filter method just wants a function and invokes it no matter how it is defined, and I wrote:
let a = new Set([1, 2, 3]);
let b = new Set([2, 3, 4]);
let intersection = [...a].filter(b.has);
console.log(intersection);
And in this case, unexpectedly, I receive the following error:
Uncaught TypeError: Method Set.prototype.has called on incompatible receiver undefined
I also noticed that this doesn't happen if I bind Set.prototype.add to the variable:
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);
My question is: why does it happen? Why b.has is not a valid callback?
has method loses internal this context when you pass it as a callback.
That is the reason it works when you use bind to provide it right context.
For more info it has been documented here
You can use the Array#filter function and pass thisArg as the second parameter. So the has will take this second parameter as it's this, and proceeds to evaluate or compare.
Here's an example:
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));
Another idea:
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()]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With