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

Предположим, у меня есть любая переменная, которая определяется следующим образом:

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

Я хочу функцию, которая проверяет, является ли тип переменной как функция. т.е.

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

Как я могу проверить, что переменная a имеет тип Function описанным выше способом?

Ответ 1

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

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

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

Ответ 2

if (typeof v === "function") {
    // do something
}

Ответ 4

Есть несколько способов, поэтому я их суммирую

  • Лучший способ:
    function foo(v) {if (v instanceof Function) {/* do something */} };
    
    
    Большинство исполнителей (без сравнения строк) и элегантного решения - оператор instanceof поддерживается в браузерах в течение очень долгого времени, поэтому не беспокойтесь - он будет работать в IE 6.
  • Следующий лучший способ:
    function foo(v) {if (typeof v === "function") {/* do something */} };
    
    
    Недостатком typeof является то, что он подвержен молчаливому сбою, плохо, поэтому, если у вас есть опечатка (например, "finction" ) - в этом случае `if` просто вернет false, и вы не будете знать, что у вас есть ошибка до тех пор, пока в вашем коде
  • Следующий лучший способ:
    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

Ответ 5

JQuery ( не рекомендуется начиная с версии 3.3) Reference

$.isFunction(functionName);

AngularJS Ссылка

angular.isFunction(value);

Lodash Ссылка

_.isFunction(value);

Подчеркнуть Ссылка

_.isFunction(object); 

Node.js устаревшим с V4.0.0 Reference

var util = require('util');
util.isFunction(object);

Ответ 6

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

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

Ответ 7

var foo = function(){};
if (typeof foo === "function") {
  alert("is function")
}

Ответ 8

Попробуйте оператор instanceof: кажется, что все функции наследуются от класса Function:

// Test data
var f1 = function () { alert("test"); }
var o1 = { Name: "Object_1" };
F_est = function () { };
var o2 = new F_est();

// Results
alert(f1 instanceof Function); // true
alert(o1 instanceof Function); // false
alert(o2 instanceof Function); // false

Ответ 9

Другой простой способ:

var fn = function () {}
if (fn.constructor === Function) {
  // true
} else {
  // false
}

Ответ 10

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

Следующий код содержит только чистые и точечные функции:

const R = require('ramda');

const isPrototypeEquals = R.pipe(Object.getPrototypeOf, R.equals);

const equalsSyncFunction = isPrototypeEquals(() => {});

const isSyncFunction = R.pipe(Object.getPrototypeOf, equalsSyncFunction);

Начиная с ES2017, доступны async функции, поэтому мы также можем проверить их:

const equalsAsyncFunction = isPrototypeEquals(async () => {});

const isAsyncFunction = R.pipe(Object.getPrototypeOf, equalsAsyncFunction);

А затем объединить их вместе:

const isFunction = R.either(isSyncFunction, isAsyncFunction);

Конечно, функция должна быть защищена от null и undefined значений, чтобы сделать ее "безопасной":

const safeIsFunction = R.unless(R.isNil, isFunction);

И полный фрагмент, чтобы подвести итог:

const R = require('ramda');

const isPrototypeEquals = R.pipe(Object.getPrototypeOf, R.equals);

const equalsSyncFunction = isPrototypeEquals(() => {});
const equalsAsyncFunction = isPrototypeEquals(async () => {});

const isSyncFunction = R.pipe(Object.getPrototypeOf, equalsSyncFunction);
const isAsyncFunction = R.pipe(Object.getPrototypeOf, equalsAsyncFunction);

const isFunction = R.either(isSyncFunction, isAsyncFunction);

const safeIsFunction = R.unless(R.isNil, isFunction);

// ---

console.log(safeIsFunction( function () {} ));
console.log(safeIsFunction( () => {} ));
console.log(safeIsFunction( (async () => {}) ));
console.log(safeIsFunction( new class {} ));
console.log(safeIsFunction( {} ));
console.log(safeIsFunction( [] ));
console.log(safeIsFunction( 'a' ));
console.log(safeIsFunction( 1 ));
console.log(safeIsFunction( null ));
console.log(safeIsFunction( undefined ));

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

Ответ 11

Если вы используете Lodash, вы можете сделать это с помощью _. isFunction.

_.isFunction(function(){});
// => true

_.isFunction(/abc/);
// => false

_.isFunction(true);
// => false

_.isFunction(null);
// => false

Этот метод возвращает true, если значение является функцией, else false.

Ответ 12

Я обнаружил, что при тестировании собственных функций браузера в IE8 использование toString, instanceof и typeof не работает. Вот метод, который отлично работает в IE8 (насколько я знаю):

function isFn(f){
    return !!(f && f.call && f.apply);
}
//Returns true in IE7/8
isFn(document.getElementById);

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

"getElementById" in document

Хотя, я где-то читал, что это не всегда будет работать в IE7 и ниже.

Ответ 13

Нижеследующее, похоже, работает и для меня (проверено с node.js):

var isFunction = function(o) {
     return Function.prototype.isPrototypeOf(o);
};

console.log(isFunction(function(){})); // true
console.log(isFunction({})); // false

Ответ 14

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

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

а затем проверить это как:

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({}); //false
isFunction([]); //false
isFunction("function"); //false
isFunction(true); //false
isFunction(1); //false
isFunction("Alireza Dezfoolian"); //false

Ответ 15

Так как node v0.11, вы можете использовать стандартную функцию утилиты:

var util = require('util');
util.isFunction('foo');

Ответ 16

Я думаю, вы можете просто определить флаг в прототипе Function и проверить, если экземпляр, который вы хотите проверить, унаследовал, что

определить флаг:

Function.prototype.isFunction = true; 

, а затем проверьте, существует ли он

var foo = function(){};
foo.isFunction; // will return true

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

Ответ 17

вы должны использовать typeOf оператор в js.

var a=function(){
    alert("fun a");
}
alert(typeof a);// alerts "function"

Ответ 18

Решение, как показано в некоторых предыдущих ответах, это использовать typeof. ниже приведен фрагмент кода в NodeJs,

    function startx() {
      console.log("startx function called.");
    }

 var fct= {};
 fct["/startx"] = startx;

if (typeof fct[/startx] === 'function') { //check if function then execute it
    fct[/startx]();
  }