Как я могу проверить, является ли переменная javascript типом функции?



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



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


мне нужна функция, которая проверяет, является ли тип переменной функциональным. т. е. :



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


Как я могу проверить, является ли переменная ' a ' функцией типа так, как определено выше?

285   17  

17 ответов:

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

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

function isFunction(functionToCheck) {
 return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}
if (typeof v === "function") {
    // do something
}

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

_.isFunction = function(obj) {
  return !!(obj && obj.constructor && obj.call && obj.apply);
};

см.:http://jsperf.com/alternative-isfunction-implementations

EDIT: обновленные тесты показывают, что typeof может быть быстрее, см. http://jsperf.com/alternative-isfunction-implementations/4

есть несколько способов, так что я буду суммировать их все

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

jQueryссылка

$.isFunction(functionName);

AngularJSссылка

angular.isFunction(value);

Лодашьссылка

_.isFunction(value);

подчеркиваниессылка

_.isFunction(object); 

узел.js считается устаревшим, начиная с версии V4.0.0 ссылка

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

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

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

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

попробуйте 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

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

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

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

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

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 ));

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

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

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

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

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

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

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

я обнаружил, что при тестировании собственных функций браузера в 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 и ниже.

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

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

Function.prototype.isFunction = true; 

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

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

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

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

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

ниже, кажется, работает и для меня (проверено с node.js):

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

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

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

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

решение, как показали некоторые предыдущие ответы, заключается в использовании 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]();
  }

Comments

    Ничего не найдено.