Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set.prototype.has() with predicate

Tags:

javascript

var myset = new Set();
    
myset.add({ key: 123, value: 100 });
var has = myset.has({ key: 123, value: 100 });    
console.log(has); // false
       
var obj = {
    key: 456,
    value: 200
};

myset.add(obj);
has = myset.has(obj);
console.log(has); // true
    
has = myset.has(x => x.key === 123);    
console.log(has); // false

The problem in this case: I just add { key: 123, value: 100 } to myset, why doesn't it contain { key: 123, value: 100 }?

Another case, if I use obj instead of { key: 123, value: 100 }, it would return true.

Set.prototype.has() says:

The has() method returns a boolean indicating whether an element with the specified value exists in a Set object or not.

But that doesn't mention about: what's specified value?

Clearly, in this case { key: 123, value: 100 } and { key: 123, value: 100 } are similar to, and.... I'm getting false. So what's specified here?

And the second question: why doesn't they support predicate in has() method?

In my example. It's harder to search if I use for...of...:

for (let obj of myset) {
    if (obj.key === 123) return true;
}

While it can be inline with predicating:

has = myset.has(x => x.key === 123)

So, should it be improved for future?

like image 537
Tân Avatar asked Oct 19 '22 03:10

Tân


2 Answers

Set.prototype.has doesn't find the object because it tests using value equality, meaning:

{ key: 123 } !== { key: 123 } // true

If you want to be able to find an item based on a predicate, you will have to add that function manually. The function probably doesn't exist already because a Set is only efficient when you need fast lookups without iteration. If you want to iterate values, use an array instead.

Here's how you could implement it just as Array.prototype.find:

Set.prototype.find = function () {
    return Array.prototype.find.apply([...this], arguments);
};
like image 140
4castle Avatar answered Oct 20 '22 23:10

4castle


{ key: 123, value: 100 } === { key: 123, value: 100 } is false because JavaScript performs a shallow comparison. Each object literal creates a new object, they may hold the same values, but they are still different objects that just happens to look alike.

var a = {};
var b = a;
a === b; // true 

In this example you get true because now you are comparing the same object. You can tell that a, and b are the same object because changes in a are reflected in b.

a.x = 1;
b.x === 1; // true

myset.has(x => x.key === 123) here you are asking if the set has this new lambda that you just created. It would be nice if has used your lambda to check the elements of the set, but unfortunately the method does perform this check.

like image 20
Rodrigo5244 Avatar answered Oct 20 '22 22:10

Rodrigo5244