использование Set.has в Array.filter - несовместимый получатель - PullRequest
0 голосов
/ 26 мая 2018

Предположим, у меня есть Set в качестве справочной таблицы.

const myset = new Set(["key1", "key2", "key3", "keepMe"]);

Я хотел отфильтровать другой массив некоторых других ключей (скажем, mykeys), которые находятся в myset.

const mykeys = ["ignoreMe", "keepMe", "ignoreMeToo", "key2"];

Вопрос:

Почему я должен использовать

const filtered = mykeys.filter(k => myset.has(k))

вместо

const filtered = mykeys.filter(myset.has)
// TypeError: Method Set.prototype.has called on incompatible receiver undefined

, т. Е. Зачем создаватьанонимная лямбда-функция в фильтре?keys.has имеет такую ​​же подпись (аргумент - элемент, возвращаемый логический).Один мой друг сказал мне, что это связано с this.

, тогда как mykeys.map(console.log) работает без ошибок (хотя и бесполезно).

Я наткнулся на эту статью в MDN и я до сих пор не понимаю, почему «myset» не фиксируется как этот ».Я понимаю обходной путь, но не "почему".Кто-нибудь может объяснить это некоторыми подробностями и ссылками по-человечески?

Обновление: Спасибо всем за ответы.Может быть, я не понял, о чем я спрашиваю.Я понимаю обходные пути.

@ charlietfl понял.Вот его комментарий , то, что я искал:

Поскольку filter () не имеет неявного this, где set.has должен иметь надлежащий this контекст.Вызов его внутри анонимной функции и добавление аргумента вручную делает вызов автономным.

Ответы [ 2 ]

0 голосов
/ 26 мая 2018

Вы можете использовать thisArg из Array#filter с набором и прототипом has в качестве обратного вызова.

Этот шаблон не требует привязки экземпляра Set для прототипа, поскольку

Если для filter задан параметр thisArg, он будет использоваться в качестве значения this обратного вызова.В противном случае значение undefined будет использоваться в качестве значения this.Значение this, в конечном итоге наблюдаемое callback, определяется в соответствии с обычными правилами определения этого, видимого функцией .

const
    myset = new Set(["key1", "key2", "key3", "keepMe"]),
    mykeys = ["ignoreMe", "keepMe", "ignoreMeToo", "key2"],
    filtered = mykeys.filter(Set.prototype.has, myset);

console.log(filtered);
0 голосов
/ 26 мая 2018

Это фундаментальное проектное решение, восходящее к первому определению языка JavaScript.

Рассмотрим объект

var myObjet = {
  someValue: 0,
  someFunction: function() {
    return this.someValue;
  }
};

Теперь, когда вы пишете

var myValue = myObject.someValue;

Вы получаете именно то, что вложили в него, как если бы вы написали

var myValue = 0;

Подобным образом, когда вы пишете

var myFunction = myObject.someValue;

Вы получаете именно то, что вложили в него,как если бы вы написали

var myFunction = (function() {
  return this.someValue;
});

... за исключением того, что вы больше не находитесь в объекте.Так что this ничего не значит.Действительно, если вы попробуете

console.log(myFunction());

, вы увидите

undefined

точно так же, как если бы вы написали

console.log(this.someValue);

вне любого объекта.

Итак, что такое this?Итак, JavaScript решает это следующим образом:

  • Если вы пишете myObject.myFunction(), то при выполнении части myFunction() this равно myObject.
  • Если вы простонапишите myFunction(), тогда this - текущий глобальный объект, который обычно равен window (не всегда, есть много особых случаев).
  • Ряд функций может вставлять this в другойфункция (например, call, apply, map, ...)

Теперь, почему это происходит?Ответ в том, что это необходимо для прототипов.Действительно, если вы теперь определите

var myDerivedObject = Object.create(myObject);
myDerivedObjet.someValue = 42;

, у вас теперь есть объект, основанный на myObject, но с другим свойством someValue

console.log(myObject.someFunction()); // Shows 0
console.log(myDerivedObject.someFunction()); // Shows 42

Это потому, что myObject.someFunction() использует myObject для this, тогда как myDerivedObject.someFunction() использует myDerivedObject для this.

Если бы this было захвачено во время определения someFunction, мы получили бы 0 в обоихлиний, но это также сделало бы прототипы гораздо менее полезными.

...