2016-08-15 2 views
4

Set.prototype.has() с предикатом

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

Проблема в данном случае: Я просто добавить { key: 123, value: 100 } к myset, почему она не содержит { key: 123, value: 100 }?

Другой случай, если я использую obj вместо { key: 123, value: 100 }, он вернет true.

Set.prototype.has() говорит:

Метод имеет() возвращает логическое значение, указывающее, существует ли элемент с указанным значением в объекте Set или нет.

Но это не говорит о том, что такое specified value?

Очевидно, что в этом случае { key: 123, value: 100 } и { key: 123, value: 100 } похожи на, и .... Я получаю false. Итак, что здесь specified?

И второй вопрос: почему они не поддерживают predicate в has() методе?

В моем примере. Это труднее найти, если я использую for...of...:

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

Хотя это может быть рядный с утверждающий:

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

Таким образом, она должна быть улучшена для будущего?

+3

https://esdiscuss.org/topic/maps-with-object-keys да, извините. Карты JS нарушены для практических случаев использования, и человек, который сказал, что он их исправит, не собирается. Он не поддерживает предикаты или структурное равенство, потому что работа на языке - это неблагодарная работа, требующая тысяч часов, и большинство людей не хотят ее вставлять. –

+0

@BenjaminGruenbaum ya. Благодаря! Я жду ECMAScript 2018 :) –

ответ

1

{ key: 123, value: 100 } === { key: 123, value: 100 } is false потому что JavaScript выполняет мелкое сравнение. Каждый литерал объекта создает новый объект, он может содержать одни и те же значения, но они все еще разные объекты, которые просто выглядят одинаково.

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

В этом примере вы получите true, потому что теперь вы сравниваете один и тот же объект. Вы можете сказать, что a и b - это тот же объект, потому что изменения в a отражены в b.

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

myset.has(x => x.key === 123) здесь вы спрашиваете, если набор этой новой лямбда, который вы только что создали. Было бы неплохо, если бы has использовал вашу лямбду, чтобы проверить элементы набора, но, к сожалению, этот метод выполняет эту проверку.

1

Set.prototype.has не находит объект, поскольку он проверяет с помощью value equality, что означает:

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

Если вы хотите, чтобы иметь возможность найти элемент, основанный на предикате, вы должны добавить эту функцию вручную. Функция, вероятно, не существует уже потому, что Set эффективен только тогда, когда вам нужны быстрые поиски без итерации. Если вы хотите итерировать значения, используйте вместо этого массив.

Вот как вы могли бы реализовать его как Array.prototype.find:

Set.prototype.find = function() { 
    return Array.prototype.find.apply([...this], arguments); 
}; 
Смежные вопросы