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

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

我想要一个函数来检查变量的类型是否为类函数。例如:

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

我怎样才能检查变量a是否为上述定义的函数类型?


当前回答

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

下面的代码只包含纯函数和无点函数:

const R = require('ramda');

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

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

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

从ES2017开始,异步函数是可用的,所以我们也可以检查它们:

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

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

然后把它们组合在一起:

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

当然,函数应该被保护不受空值和未定义值的影响,所以为了使它“安全”:

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

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

其他回答

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

function isFunction(x) {
  return Object.prototype.toString.call(x) == '[object Function]';
}
if (typeof v === 'function') {
    // do something
}

下面的代码似乎也适用于我(从node.js测试):

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

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

有几种方法,所以我将把它们都总结一下

Best way is: function foo(v) {if (v instanceof Function) {/* do something */} }; Most performant (no string comparison) and elegant solution - the instanceof operator has been supported in browsers for a very long time, so don't worry - it will work in IE 6. Next best way is: function foo(v) {if (typeof v === "function") {/* do something */} }; disadvantage of typeof is that it is susceptible to silent failure, bad, so if you have a typo (e.g. "finction") - in this case the if will just return false and you won't know you have an error until later in your code The next best way is: function isFunction(functionToCheck) { var getType = {}; return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; } This has no advantage over solution #1 or #2 but is a lot less readable. An improved version of this is function isFunction(x) { return Object.prototype.toString.call(x) == '[object Function]'; } but still lot less semantic than solution #1

你应该在js中使用typeOf操作符。

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