, чтобы сохранить свой прогресс
Николай Ланец
20 сент. 2021 г., 20:44

Обсуждение задания "Profile Lookup"

Очень интересный урок, который хотелось бы обсудить... К своему удивлению, я не нашел здесь во всех уроках по Javascript уроков, касающихся методов типа Array.find(), Array.filter(), Array.findIndex() и т.п. При этом это очень полезные методы, используемые чуть ли не каждый день. И на мой взгляд они, во-первых, более короткие, чем конструкции типа for(...), а во-вторых, более логичны в плане восприятия.

Сразу отмечу, что я не хочу сказать, что другие решают не правильно. Я просто хочу показать другие варианты.

Сравним код большинства ответов в этой задаче:

function lookUpProfile(name, prop){ // Only change code below this line for (let i = 0; i < contacts.length; i++){ if (contacts[i].firstName === name){ if (contacts[i][prop]){ return contacts[i][prop]; } return "No such property"; } } return "No such contact"; // Only change code above this line }
и одно из моих решений:

function lookUpProfile(name, prop) { // Only change code below this line const item = contacts.find(n => n.firstName === name); if (item) { if (item[prop] === undefined) { return 'No such property'; } return item[prop]; } else { return 'No such contact'; } // Only change code above this line }
Какое решение вам кажется более наглядным?
Как мне кажется, вариант с перечислением for (let i = 0; i < contacts.length; i++) более громоздкий и в нем больше отвлекающих переменных. То есть мы создаем переменную-счетчик i, сравниваем ее со значением длины массива, каждую итерацию увеличиваем ее значение, используем для получения элемента массива и т.п., и все это вместо того, чтобы работать просто с массивом и его элементами.
В моем варианте используется метод массива find(condition). Уточню, что прототипом всех массивов является Array. Соответственно, все методы его наследуются и конечным массивам. Метод find(condition) принимает в качестве параметра функцию, используемую для поиска элемента в текущем массиве (первого, удовлетворяющего условию). То есть массив перечисляет все свои элементы до тех пор, пока применяемая к ним функция не вернет истину (или то, что может быть преобразовано в логическое true). В моем случае это n => n.firstName === name.
Для кого-то данная конструкция может быть не понятна, уточню: это стрелочная функция. Если переводить на более понятный синтаксис, то это так:
function condition (n){ return n.firstName === name; }
Подробней о стрелочных функциях в этом уроке.


Итак, применив метод Array.find() вместо перечисления for(...) я попытался найти нужный мне элемент.
const item = contacts.find(n => n.firstName === name);

В данном случае (если понять синтаксис) все сильно понятней и логичней: я выполнил метод поиска у самого массива и получил найденный элемент из него и присвоил в переменную item (или присвоил undefined, если элемент не был найден).

Далее я уже работаю с проверками на самом элементе
if (item) { if (item[prop] === undefined) { return 'No such property'; } return item[prop]; } else { return 'No such contact'; }
То есть вроде тоже все понятно: если элемент item есть, то в нем проверяю значение, если нет, то возвращаю сообщение об ошибке. И никаких лишних i и т.п.


В погоне за сокращением можно и вовсе вот так написать:
function lookUpProfile(name, prop) { const item = contacts.find(n => n.firstName === name); return !item ? 'No such contact' : item[prop] || 'No such property' }
То есть я сразу проверил есть ли объект и если нет, возвращяю 'No such contact', иначе возвращаю свойство объекта (если оно есть) или сообщение 'No such property'

Да, такой стиль может показаться более сложным и запутанным, но сейчас чаще именно так и пишут, потому что меньше кода - меньше над чем думать приходится.

Если правильно понимаю - и по времени быстрее должно работать?
Совершенно не факт. Нужно тестирование проводить. Хотя вряд ли разница будет ощутимая. Но есть разница в восприятии и объеме кодовой базы.

Добавить комментарий