Искусство делать наш код более общим и избегать повторений

Начнем с обзора наших знаний о функциях.

Мы знаем, что функции в Javascript являются объектами.
Мы также сказали, что когда мы вызываем функцию, мы автоматически получаем два параметра: this ключевое слово и arguments ключевое слово.



Мы увидели, что arguments представляет собой объект, похожий на массив, со странным поведением при циклических и итерациях, поэтому мы не хотим его использовать. Вместо этого мы можем использовать что-то вроде оператора распространения.

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

Мы увидели, что когда мы определяем наши функции, компилятор смотрит на наш код лексически и определяет, какие переменные доступны для нас в нашей среде переменных, а также добавляет цепочки областей видимости.



Вызов функции

Мы видели несколько способов вызова функций.

  1. Первый метод нам хорошо знаком.

2. Второй способ, который мы видели, - это метод. Метод - это функция внутри объекта.

Мы можем упростить эту функцию с помощью нового скрипта ECMA.

Обратите внимание, что здесь obj вызывает two (), ключевое слово this заменяется на obj, а не на окно.

3. Третий способ использования функций - использовать call.



Основы Javascript: call () и apply ()
Управление этим medium.com



4. Это три основных способа, но есть еще один, который вы не увидите очень часто.

Это называется конструктор функции.

Наши встроенные объекты, которые поставляются с языком Javascript, создают для нас функции. Здесь первый параметр - это то, что мы хотим, чтобы задача функции была возвращена 4.

Но у нас также могут быть параметры.

Я все еще получаю четыре.
Все, что указано в последнем параметре функции, будет фактическим телом кода.

Функции - это объекты.

Это то, что не очень часто встречается в других языках. В Javascript я могу сделать что-то вроде этого:

Под капотом Javascript создает объект особого типа, называемый вызываемым объектом. Что-то вроде этого:

Этот код, конечно, не сработает. Это псевдокод, чтобы показать вам, что происходит под капотом.

Подводя итог, если бы у нас была функция someFunc (), это был бы объект с тремя специальными свойствами:

1. code (): В нем будет фрагмент кода, который мы можем вызвать с помощью двух скобок. Когда мы вызываем с этими скобками, он читает все, что находится в этих скобках, и выполняет его.

2. Имя (необязательно): например, если функция называется someFunc, имя будет someFunc. Но помните, что у нас также есть анонимные функции.
Если бы мы использовали выражение функции, присвойте его var, но сама функция анонимна, ну, имя не существовало бы, потому что оно необязательно.

3. Свойства: мы автоматически получаем свойства функции. У нас есть такие свойства, как call (), apply () и bind (), которые позволяют нам работать с этой функцией.

Например, если я вернусь к Woohoo,

У нас также есть такие свойства, как аргументы, длина, имя.

Объекты

Что касается объектов, у меня нет тех свойств и методов, которые мы видели, таких как call (), bind (), apply () или любое из свойств.

Помните, что функции - это объекты, но это особый тип объекта. Вызываемый объект с обозначением скобок для вызова функции содержит код, у него есть имя, а также некоторые свойства, такие как call, apply и bind.

Почему это важно?

Поскольку функции в Javascript являются просто объектами, мы можем передавать их как объекты или вещи, содержащие данные.

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

Первоклассный гражданин

Поскольку функции могут передаваться как данные, помимо простого выполнения действий с нашим кодом, вы услышите, как люди говорят, что функции - это первоклассный гражданин в Javascript.

Это означает три вещи:

  1. Функции можно назначать переменным и свойствам объектов.
    Так что я могу:

var stuff = function () {};

На некоторых языках я не могу этого сделать. Я могу просто запускать функции для выполнения действий и все. В Javascript я могу назначить его переменной или свойству объекта, которое затем становится методом.

2. Мы также можем передавать функции в качестве аргументов в функцию. Так что я могу:

3. Мы можем возвращать функции как значения из других функций. Что это обозначает?

Или я могу присвоить его переменной, а затем просто вызвать эту переменную d.

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

Итак, функции - это данные, потому что они не только выполняют действия за нас, но и могут передаваться, как если бы они были типами Javascript. Так что все, что вы можете делать с другими типами, вы можете делать с функцией.

Эта идея первоклассного свойства вводит Javascript в целый мир, называемый функциональным программированием.

Чего следует избегать при использовании функций

  1. Избегайте инициализации функций внутри циклов.

Здесь каждый раз, когда мы зацикливаемся, например, когда i = 0, мы собираемся инициализировать функцию a, а затем запускать ее. То же самое, когда i = 1, мы инициализируем функцию a, затем вызываем функцию и так далее.

Вместо того, чтобы инициализировать функцию внутри цикла, мы должны переместить функцию наверх. Так что инициализируем функцию только один раз. Когда мы перебираем его, мы просто выполняем его пять раз вместо того, чтобы инициализировать и выполнять.

2. Вот еще одна вещь, о которой нам следует остерегаться:

Моя функция выдает ошибку ссылки, потому что param не находится ни в локальной, ни в глобальной области.

Как только у нас нет ничего в нашей переменной окружения или цепочке областей видимости, мы получаем справочную ошибку.
Обычно это приводит к сбою многих функций и требует от нас выполнения какой-то проверки, чтобы увидеть, существует ли параметр.

Конечно, мы могли бы добавить параметр

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

Но когда мы вызываем его ни с чем, мы просто получаем undefined. Один из способов избежать этого - просто дать ему параметр по умолчанию, который идет с Es6.

Теперь, если я запускаю это, вместо undefined я получаю 6. Так что хорошо иметь параметры по умолчанию, установленные как способ избежать этих крайних случаев.

Функции высшего порядка

HOF - это функции, которые могут принимать функцию в качестве аргумента или функцию, возвращающую другую функцию.

Почему нам нужно заботиться о HOF?

Во-первых, давайте посмотрим, какие проблемы мы можем решить с помощью простой функции.

Предположим, у нас есть корпоративная система, которая позволяет нашим пользователям входить в систему.

С этой функцией есть задержка - требуется время, чтобы предоставить доступ к адаму. А если мы добавим еще один ноль, все будет очень медленно.

Теперь помните, что мы предполагаем, что это служба аутентификации, которая есть в нашей компании. Но что, если у нас есть больше сотрудников, которых мы хотим аутентифицировать.

Допустим, у нас есть Ева.
Нам нужно будет создать еще одну функцию аутентификации для Евы.

Но теперь у нас возникла проблема с этим кодом; Не так ли? Мы не храним наш код в СУХОМ виде. Мы повторяемся. Созданный нами код негибкий.

Для каждого пользователя, который у нас есть, мы должны копировать и вставлять код и повторяться. Только представьте, если бы у нас были сотни и сотни сотрудников, делать это каждый раз было бы неплохо.

Итак, как мы можем это исправить?

Давайте перейдем от одной функции к функции, которая принимает параметры.

Поэтому вместо функций letAdamLogin и letEvaLogin давайте создадим общую функцию letUserLogin.

А для Евы:

Теперь давайте реорганизуем код, чтобы он стал чище, создав еще одну функцию giveAccess.

Поэтому я могу просто вернуть giveAccessTo.

Мы поднялись здесь. Теперь мы сообщаем функции, какие данные использовать при ее вызове.

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

Так что вместо определения Евы или Адама внутри функции мы можем просто определить это позже, когда просто вызовем функцию

Таким образом, у нас есть возможность определять данные при вызове функции. У нас есть немного гибкости. Мы сохранили наш код СУХОЙ.

Но какие здесь ограничения?

Что, если вместо пользователей у нас будет еще и администратор - кто-то с гораздо большими привилегиями?

Тогда нам пришлось бы скопировать код

Теперь вы заметили, что, поскольку его администратор, мы должны пройти немного больше процедур, отсюда и «5000000» - скажем, им требуется немного больше времени для аутентификации.

Итак, функция немного изменилась - у нас другой процесс разрешения. Но все же мы просто скопировали еще код. Мы не очень СУХИЕ.
А представьте, если бы нам пришлось давать доступ менеджерам, секретарям, гостевой доступ и так далее.

Итак, что мы можем здесь сделать?

Здесь могут сыграть роль функции высшего порядка.

Помните, что мы перешли от простых функций function () к функциям с параметрами function (a, b). Это означало, что вместо того, чтобы просто определять функцию и точно сообщать ей, что делать и какие данные использовать, мы можем определить, что функция делает, но позже, когда мы вызываем функцию, мы сообщаем ей, какие данные нам нужны.

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

Так как это будет работать?

Во-первых, давайте создадим функцию аутентификации, которая принимает параметр - в нашем случае число, которое является временем аутентификации. Это процесс проверки.

У нас есть функции Authenticate и giveAccess. Как теперь улучшить остальные функции?

Давайте удалим функции let letUserLogin и letAdminLogin и вместо этого создадим общую функцию letPerson.

Так как же это упростило задачу?

Теперь мы можем:

Это работает.
И если я перейду на админа:

Это тоже работает.

Так какую же силу мы получили здесь?

Теперь у нас есть возможность не только указывать ему, какую мощность использовать, но и что делать.

Мы создали универсальную функцию letPerson по сравнению с предыдущей функцией letAdamLogin. Это было слишком конкретно. letPerson принимает в качестве первого параметра человека, а затем функцию, в данном случае аутентификацию в качестве второго параметра.

Итак, делая вещи общими, теперь мы можем добавить что-то вроде функции sing:

Наша функция letPerson теперь носит более общий характер - это функция высшего порядка, поскольку она принимает функцию в качестве параметра, теперь я могу добавить еще много функций:

Мы удалили функцию giveAccessTo и добавили ее в Authenticate и просто вернули несколько общих функций в letPerson, чтобы эта функция работала.

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

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

Имея это на месте, я теперь могу сохранить свою функцию в другой переменной, скажем:

Теперь у меня есть эта функция, которую я могу использовать повторно, где могу:

Я могу использовать эту функциональность снова и снова с помощью этой функции высшего порядка.

Здесь multiplyBy является функцией высшего порядка, поскольку она возвращает другую функцию.

Я также могу расширить это там, где могу

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

Все его слова таковы:
Дайте мне параметр, а затем другой параметр. Итак, если я просто сделаю:

И это все, что вам показывают эти скобки, и теперь я надеюсь, что мы можем увидеть мощь HOF.

Мы узнали, как перейти от простой функции () к функции с параметрами function (a, b) к функциям более высокого порядка. Основное преимущество состоит в том, что мы можем сделайте наш код более общим - СУХИМ, мы не повторяемся, и у нас есть возможность разбить вещи на большее количество функций.