Написание моей версии _.reject в Underscore JS - PullRequest
0 голосов
/ 05 марта 2020
  // Return all elements of an array that pass a truth test.
  _.filter = function(collection, test) {
    var result = []; //make a result variable 
    //iterate over the collection array using _.each
    _.each(collection, function(value) {
    //if conditions for test(element) = positive
      if (test(value)) {
        //push element into result
        result.push(value);
      }
    });
    return result;
  };

Привет, я работаю над переписыванием функции _.filter & _.reject из библиотеки Underscore JS. Я все еще немного запутался в функциях обратного вызова, особенно когда в одной и той же функции их так много. Мне нужно кое-что прояснить по поводу моих мыслей и логики c здесь; особенно о ._reject. Я повторно использую свою функцию _.filter и реализую ее в своей _.reject забаве c.

 _.reject = function(collection, test) {
    return _.filter(collection, function(value) {
      return !test(value);
    })
  };

Когда у меня есть функция (значение) в качестве параметра для фильтра и определил его; это заменяет мое тестовое значение обратным вызовом этих функций? В частности, в этой строке - if (test(value)) {... заменяет ли это мой обратный вызов в этом случае if(function(value) {return !test(value)}) Кроме того, если я опускаю команду return из моей функции _.reject для _.filter; я просто возвращаю саму функцию? Извините - я знаю, что это немного странно, так как мой код работает, насколько я знаю, но это была действительно большая попытка попробовать что-то, а не понять логически. Я просто очень запутался в том, что происходит, когда я вызываю функцию обратного вызова в фильтре из моей функции отклонения

1 Ответ

1 голос
/ 05 марта 2020

В JavaScript все является объектом, включая функции. Когда вы пишете выражение функции (как они вызываются) следующим образом:

const foo = function() {
  console.log('This function prints this message!');
};

foo теперь содержит ссылку на функцию, которая печатает сообщение. Мы можем назвать это так:

foo();

… который запускает код и печатает сообщение. Вы можете передавать foo как любое другое значение, в том числе в качестве параметра для других функций. Думайте об этом как о сохранении набора инструкций для выполнения каких-либо действий: вы говорите компьютеру "foo содержит код, который при запуске печатает сообщение."

В вашем примере выражение функции, которое вы передаете в качестве второго аргумента _.filter объект:

function(value) {
  return !test(value);
}

Вы говорите: «Передайте эту функцию, которая принимает значение, вызывает test с ним, сводит на нет результат, и возвращает его в мою _.filter функцию. " _.filter знает, как вызвать эту функцию для фильтрации значений.

Программирование полно таких видов паттернов: цель не в том, чтобы взглянуть на то, что происходит, вниз, это чтобы понять, что _.filter принимает второй параметр, это функция, которая говорит: «Если вы дадите мне значение, я скажу вам, нужно ли его сохранить». И в вашем коде вы передаете ему функцию, которая делает это, но она также вызывает другую функцию (test), которую передал ваш пользователь. Цепочки вызовов функций могут быть длинными: сотни или тысячи функций, вызывающих другие функции.

В вашем случае, похоже, ваш код правильный. _.filter говорит: «Дайте мне массив данных и функцию. Я вызову эту функцию для каждого значения в массиве, и он вернет мне, сохранять ли его». Вы создаете функцию, которая говорит: «Дайте мне массив данных и функцию. Я вызову эту функцию для каждого значения в массиве, и он вернет мне, если не , чтобы сохранить его. " Для этого вы просто инвертируете то, что _.filter хочет знать: вместо того, чтобы вести запись, вы хотите знать, следует ли ее удалить.

Таким образом, ваш код дает массив пользователя и функцию до _.filter так, как он хочет. Функция вызывается с каждым элементом массива. _.filter хочет знать, сохранить ли предмет. Вы собираетесь позвонить test с предметом, о котором вас спрашивает _.filter. Но если пользовательская функция возвращает true, мы хотим исключить элемент, а не сохранить его, поэтому мы отрицаем это (с помощью !) и возвращаем значение. Затем вы возвращаете результат _.filter.

Чтобы уточнить о return: ключевое слово return сообщает функции, вызывающей вашу функцию , что вы хотите «вернуть» , Поэтому, когда вы return !test(value), вы говорите , что называется вашей функцией , значением !test(value) (в данном случае это _.filter). Если бы вы не использовали return, вы бы ничего не возвращали к коду, который вызывал вашу функцию. Если пользователь хочет знать, как выглядит массив после отклонения элементов, а ваша функция ничего не сделала return, то ваша функция не очень полезна!

...