Перейти к содержимому

Js передать функцию как параметр

  • автор:

Как передать функцию в функцию js

Функция в функцию передаётся как обычный параметр, так же, как это работает с любыми другими значениями. Например:

const sayHello = () =>  console.log('Hello!'); >; const execFunc = (func) =>  func(); >; execFunc(sayHello); // => Hello! 

Частая ошибка, когда новички передают не саму функцию, а вызов функции. Будьте внимательны, при таком подходе, сначала вычислиться то, что мы передаём, затем это значение попадёт в функцию:

const sayHello = () =>  console.log('Hello!'); >; const execFunc = (func) =>  func(); >; execFunc(sayHello()); // => TypeError: func is not a function 

Ошибка возникает, потому что в функцию execFunc() передаётся не функция, а вызов функции sayHello() .

TypeScript: Функции как параметры

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

Как типизировать функции, которые передаются как параметры

Самый простой способ типизировать функции как параметры — использовать тип Function . Он описывает функцию JavaScript со всеми ее особенностями, включая свойства bind , call и apply .

Опишем входной параметр callback функции process :

function process(callback: Function) < const value = callback(); // . >

Function отключает проверку типов для вызываемой функции. В итоге количество и тип входных аргументов не проверяются, а результатом работы такой функции будет any . Это может привести к логическим ошибкам и неожиданному поведению:

process(Math.round); // ? 

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

Другой способ описывать функции — использовать стрелочную функцию с указанием входных и выходных типов:

function process(callback: () => string) < // value имеет тип string const value = callback(); // . >process(Math.round); // Argument of type '(x: number) => number' is not // assignable to parameter of type '() => string'. 

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

Рассмотрим еще несколько примеров для закрепления:

function process(callback: () => number) function process(callback: () => string[]) function process(callback: () => < firstName: string; >) 

Параметры синтаксически указываются так же, как и для стрелочных функций:

function process(callback: (n: number) => string) < const value = callback(10); // . >

Здесь мы определили тип callback функцией с параметром n с типом number и возвращаемое значение string .

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

type myFunction = (n: number) => string; function process(callback: myFunction) < const value = callback(10); // . >

Такая запись упрощает чтение кода и позволяет избежать дублирования.

Задание

Реализуйте функцию filter() , которая принимает на вход массив чисел и предикат. Последний будет использоваться для проверки каждого числа на соответствие требованиям:

const numbers = [1, -5, 2, 3, 4, 133]; filter(numbers, (n) => n > 3); // [4, 133] filter(numbers, (n) => n % 2 == 0); // [2, 4] 
  1. Массив чисел
  2. Анонимная функция, которая принимает на вход число и возвращает логическое значение

Упражнение не проходит проверку — что делать? ��

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

  • Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.

В моей среде код работает, а здесь нет ��

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя ��

Это нормально ��, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

Прочитал урок — ничего не понятно ��

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

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

Полезное

Функция как тип данных

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

Время чтения: меньше 5 мин

Открыть/закрыть навигацию по статье

  1. Кратко
  2. Как понять
    1. Хранение функции в переменной
    2. Передача функции в вызов другой функции
    3. Возвращение функции как результат вызова
    1. Николай Лопин советует

    Обновлено 20 декабря 2021

    Кратко

    Скопировать ссылку «Кратко» Скопировано

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

    Технически, функция — это объект JavaScript, у которого есть внутренний метод Call ( ) , который добавляет возможность вызова функции.

    Если вы хотите узнать о синтаксисе функций, читайте статью function .

    Как понять

    Скопировать ссылку «Как понять» Скопировано

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

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

    О функции удобно думать как об объекте, который поддерживает операцию вызова.

    Хранение функции в переменной

    Скопировать ссылку «Хранение функции в переменной» Скопировано

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

     const answer = function()  console.log('42!')> answer()// 42! const answer = function()  console.log('42!') > answer() // 42!      

    Можно сохранять в переменную и функцию, объявленную другим способом. При этом оба имени функции будут работать:

     function answerNumber()  console.log('42!')> const answer = answerNumber answerNumber()// 42!answer()// 42! function answerNumber()  console.log('42!') > const answer = answerNumber answerNumber() // 42! answer() // 42!      

    Переменная хранит ссылку на функцию, поэтому мы можем создавать столько переменных, сколько нам нужно и все они будут именами функции:

     const answer = function()  console.log('42!')> const answerNumber = answerconst fn = answer const answer = function()  console.log('42!') > const answerNumber = answer const fn = answer     

    Передача функции в вызов другой функции

    Скопировать ссылку «Передача функции в вызов другой функции» Скопировано

    Функция может передаваться в качестве аргумента при вызове другой функции.

    Например, функция, которая может выполнить произвольную операцию между двумя числами. Два числа хранятся внутри функции, а операция, которую нужно выполнить, передаётся при вызове:

     function performOperation(operation)  const a = 10 const b = 99 return operation(a, b)> const sum = performOperation(function(one, two) < return one + two >)console.log(sum)// 109 const result = performOperation(function(num1, num2) < return num1 ** (num1 / num2)>)console.log(result)// 1.2618568830660204 function performOperation(operation)  const a = 10 const b = 99 return operation(a, b) > const sum = performOperation(function(one, two)  return one + two >) console.log(sum) // 109 const result = performOperation(function(num1, num2)  return num1 ** (num1 / num2)>) console.log(result) // 1.2618568830660204      

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

    Функции, которые ожидают получить другую функцию в качестве параметра — стандартное явление в JavaScript. Даже встроенные методы, такие как for Each ( ) и filter ( ) используют этот подход.

    Функции, которые принимают другие функции или возвращают их как аргумент, называются функциями высшего порядка. Такие функции позволяют писать на JS в функциональном стиле.

    Другой случай использования — колбэки в асинхронном коде. Иногда необходимо выполнить операцию после того, как закончится какое-то действие. Например, когда пользователь кликнет на кнопку. В этом случае используется метод add Event Listener ( ) , который принимает имя события и колбэк, который нужно вызвать при его наступлении:

     document.getElementsByTagName('button')[0].addEventListener('click', function()  console.log('пользователь кликнул!')>) document.getElementsByTagName('button')[0].addEventListener('click', function()  console.log('пользователь кликнул!') >)      

    Возвращение функции как результат вызова

    Скопировать ссылку «Возвращение функции как результат вызова» Скопировано

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

     function lazySum(a, b)  return function()  return a + b >> function lazySum(a, b)  return function()  return a + b > >      

    Здесь очень легко запутаться во вложенности. При вызове lazy Sum ( ) мы передаём два аргумента. Эти аргументы не используются тут же — мы создаём новую функцию, которая складывает два числа и возвращаем её. После вызова lazy Sum ( ) мы можем сохранить эту функцию в переменную и использовать её, когда нужно:

     const performSum = lazySum(99, 1)console.log(performSum)// function lazySum() console.log(performSum())// 100 const performSum = lazySum(99, 1) console.log(performSum) // function lazySum() console.log(performSum()) // 100      

    Обратите внимание, что значения параметров a и b остаются доступны внутри вложенной функции. Эта особенность связана с контекстом выполнения и лексическим окружением функции. Такой подход также активно используется при разработке на JavaScript.

    На практике

    Скопировать ссылку «На практике» Скопировано

    Николай Лопин советует

    Скопировать ссылку «Николай Лопин советует» Скопировано

    �� Чтобы понять, что в переменной хранится функция, достаточно воспользоваться оператором typeof — для функций он возвращает строку ‘function’ :

     const answer = function()  console.log('42!')> console.log(typeof answer)// 'function' const answer = function()  console.log('42!') > console.log(typeof answer) // 'function'      

    �� Так как функция технически является объектом, то у функции есть свойства и методы. Например, свойство length вернёт количество параметров функции:

     const answer = function()  console.log('42!')> console.log(answer.length)// 0 const sum = function(a, b)  return a + b> console.log(sum.length)// 2 const answer = function()  console.log('42!') > console.log(answer.length) // 0 const sum = function(a, b)  return a + b > console.log(sum.length) // 2      

    �� Функциям можно добавлять свойства как обычным объектам. Такой код встречается редко, но не удивляйтесь, если увидите:

     const calc = function() <> calc.type = 'numbers' console.log(calc.type)// numbers const calc = function() > calc.type = 'numbers' console.log(calc.type) // numbers      

    Передать и вызвать функцию как параметр в JS?

    Я извиняюсь, за свои скупые знания. Но у меня вопрос.
    У меня есть функция. К примеру
    function test(fn1, fn2) if(fn1) <
    console.log(blabla);
    >
    else fn2;
    >
    Мне нужно что б в условии если функция fn1 вернут тру то я что то сделаю, а если фальш то хочу вызвать функцию, которая может быть разная. И я не могу ее вшить в код, так как она будет меняться в зависимости от определенных условий. Причем с параметрами надо будет вызывать. Но js мне не дает так сделать. Expected an assignment of fanction call instead saw an expression. Я конечно пробовал в коде менять на fn2() то есть вызывать ее. И вроде ок, но тогда я не смогу передать параметры при вызове.
    Что я делаю не так или это в принципе не возможно? Спасибо.

    • Вопрос задан более трёх лет назад
    • 249 просмотров

    Комментировать

    Решения вопроса 1

    Сергей Соколов @sergiks Куратор тега JavaScript

    В самом вызове test() можно обернуть исходные функции с их аргументами в функции:

    function test(fn1, fn2) < if(fn1())< console.log('blabla'); >else < fn2(); >> // в вызове оборачивайте в функции: test(() => real_function1(arg0, arg1), () => real_function2(arg3));

    Первый вариант предпочтительнее, но для разнообразия второй вариант – «привязать» к ним аргументы:

    test(real_func1.bind(null, arg1, arg2), real_func2.bind(null, arg3));

    Ответ написан более трёх лет назад

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *