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