admin管理员组

文章数量:1289483

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

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 inpatible 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?

Share Improve this question edited Aug 14, 2018 at 21:33 Christian Vincenzo Traina asked Aug 14, 2018 at 21:20 Christian Vincenzo TrainaChristian Vincenzo Traina 10.5k4 gold badges45 silver badges78 bronze badges 1
  • Does this answer your question? Method Set.prototype.add called on inpatible receiver undefined – ggorlen Commented Mar 7, 2022 at 3:25
Add a ment  | 

2 Answers 2

Reset to default 7

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 pare.

Here's an example:

function pare(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(pare(a, b));

Another idea:

function pare(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([...pare(a, b).values()]);

本文标签: javascriptMethod Setprototypehas called on incompatible receiver undefinedStack Overflow