Проверьте, имеет ли переменная тип функции
Предположим, у меня есть любая переменная, которая определяется следующим образом:
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
}
Ответ 3
Underscore.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
Ответ 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]();
}