检查变量是否为函数类型

时间:2011-05-14 05:27:47

标签: javascript

假设我有任何变量,定义如下:

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

我想要一个函数来检查变量的类型是否类似于函数。即:

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

如何以上面定义的方式检查变量a是否为Function类型?

19 个答案:

答案 0 :(得分:1471)

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

答案 1 :(得分:328)

确定下划线的方式更有效,但是当效率不成问题时,检查的最佳方法是写在由@Paul Rosania链接的下划线页面上。

受下划线的启发,最终的isFunction函数如下:

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

答案 2 :(得分:124)

Underscore.js使用了更精细但效果更好的测试:

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

请参阅:http://jsperf.com/alternative-isfunction-implementations

编辑:更新的测试表明typeof可能更快,请参阅http://jsperf.com/alternative-isfunction-implementations/4

答案 3 :(得分:89)

有几种方法可以概括所有

  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”) - 在这种情况下,`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少得多的语义

答案 4 :(得分:75)

jQuery (自3.3版以来已弃用)Reference

$.isFunction(functionName);

AngularJS Reference

angular.isFunction(value);

Lodash Reference

_.isFunction(value);

下划线 Reference

_.isFunction(object); 
自v4.0.0以来,

Node.js 已弃用Reference

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

答案 5 :(得分:54)

@grandecomplex:你的解决方案有相当多的冗长。如果这样写的话会更清楚:

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

答案 6 :(得分:46)

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

答案 7 :(得分:27)

尝试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

答案 8 :(得分:11)

另一种简单的方式:

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

答案 9 :(得分:8)

对于那些对功能样式感兴趣的人,或者在元编程中寻找更具表现力的方法(例如类型检查),看到Ramda库来完成这样的任务可能会很有趣。

下一个代码只包含pure和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);

当然,应该保护功能免受nullundefined值的影响,以便使其安全":

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

但请注意,由于大量使用高阶函数,此解决方案可能会显示出比其他可用选项更低的性能。

答案 10 :(得分:7)

具有更多浏览器支持并且还包含异步功能的内容可能是:

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

答案 11 :(得分:5)

如果您使用Lodash,则可以使用_.isFunction

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

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

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

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

如果value是函数,则此方法返回true,否则返回false

答案 12 :(得分:4)

以下似乎对我也有用(从node.js测试):

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

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

答案 13 :(得分:4)

我发现在IE8中测试本机浏览器功能时,使用toStringinstanceoftypeof不起作用。这是一个在IE8中工作正常的方法(据我所知):

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

或者,您可以使用以下方法检查本机功能:

"getElementById" in document

尽管如此,我已经在某处读过,这在IE7及以下版本中并不总是有效。

答案 14 :(得分:3)

从节点v0.11开始,您可以使用标准的util函数:

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

答案 15 :(得分:3)

我认为您可以在Function原型上定义一个标志,并检查您要测试的实例是否继承了

定义一个标志:

Function.prototype.isFunction = true; 

,然后检查是否存在

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

缺点是另一个原型可以定义相同的标志然后它没有价值,但如果您完全控制所包含的模块,那么这是最简单的方法

答案 16 :(得分:1)

您应该在js。

中使用 typeOf运算符
var a=function(){
    alert("fun a");
}
alert(typeof a);// alerts "function"

答案 17 :(得分:0)

以前的答案显示的解决方案是使用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]();
  }

答案 18 :(得分:0)

注意这一点:

typeof Object === "function" // true.
相关问题