12

Проверка, является ли переменная функцией

9

Я столкнулся с проблемой проверки типа переменной в JavaScript. У меня есть переменная, определенная следующим образом:

var a = function() {/* Statements */};

Мне нужна функция, которая проверяет, является ли тип переменной "функцией". То есть, я хочу реализовать что-то вроде этого:

function foo(v) { 
    if (v is function type?) {
        /* do something */
    }
};
foo(a);

Как мне проверить, является ли переменная a типом Function в описанном выше формате?

5 ответ(ов)

23

В данном фрагменте кода проверяется, является ли переменная v функцией. Если она действительно является функцией (то есть тип v равен 'function'), то выполняется блок кода, в котором указано // do something. Этот подход позволяет избежать ошибок, связанных с вызовом не функции, и гарантирует, что код в этом блоке будет выполнен только в том случае, если v соответствует ожидаемому типу.

Пример использования:

if (typeof v === 'function') {
    v(); // вызовем функцию v, если она действительно функцией
} else {
    console.error('Переменная v не является функцией');
}

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

4

Конечно, способ с использованием библиотеки Underscore более эффективен, но лучший способ проверки, когда эффективность не является критичным фактором, описан на странице Underscore, ссылку на которую привел @Paul Rosania.

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

function isFunction(functionToCheck) {
    return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}

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

2

Существует несколько способов, поэтому я кратко подведу итоги:

  1. Лучший способ:

    function foo(v) { if (v instanceof Function) {/* делаем что-то */} };
    

    Это наиболее производительное (без сравнений строк) и элегантное решение — оператор instanceof поддерживается в браузерах уже очень давно, так что не беспокойтесь — это будет работать даже в IE 6.

  2. Следующий лучший способ:

    function foo(v) { if (typeof v === "function") {/* делаем что-то */} };
    

    Недостаток typeof заключается в том, что он подвержен тихим сбоям, что плохо. Если вы допустите опечатку (например, "finction"), то в этом случае if просто вернет false, и вы не узнаете о вашей ошибке до более позднего момента в коде.

  3. Следующий по качеству способ:

    function isFunction(functionToCheck) {
        var getType = {};
        return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
    }
    

    У этого варианта нет преимуществ перед решениями #1 или #2, но он гораздо менее читаем. Улучшенная версия выглядит так:

    function isFunction(x) {
        return Object.prototype.toString.call(x) == '[object Function]';
    }
    

    Тем не менее, она все еще менее семантична, чем решение #1.

0

@grandecomplex: Ваше решение довольно многословно. Было бы гораздо понятнее, если бы его записать так:

function isFunction(x) {
  return Object.prototype.toString.call(x) === '[object Function]';
}
0

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

const isFunction = value => value ? (Object.prototype.toString.call(value) === "[object Function]" || "function" === typeof value || value instanceof Function) : false;

Затем вы можете протестировать его следующим образом:

isFunction(isFunction); // true
isFunction(function(){}); // true
isFunction(() => {}); // true
isFunction(() => { return 1 }); // true
isFunction(async function asyncFunction(){}); // true
isFunction(Array); // true
isFunction(Date); // true
isFunction(Object); // true
isFunction(Number); // true
isFunction(String); // true
isFunction(Symbol); // true
isFunction({}); // false
isFunction([]); // false
isFunction("function"); // false
isFunction(true); // false
isFunction(1); // false
isFunction("Alireza Dezfoolian"); // false

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь