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

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

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

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

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


当前回答

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

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

其他回答

如果你正在寻找一个简单的解决方案:

 function isFunction(value) {
   return value instanceof Function
}

这是一个老问题,但在2022年有一些考虑:

首先,浏览器兼容性:所有现代浏览器以及Deno和NodeJS都支持instanceof。 此外,它在语法上可读,比typeof更友好。 最后,它提供了比字符串比较更好的性能,但比typeof慢。因此,对我来说,这是一个很好的选择

Const FNC = () => {} const isFunction = f => !f && f instanceof函数 const isFunctionFaster = f => !!F && 'function' ===类型的F console.log ({ isFunction: isFunction (fnc), isFunctionFaster: isFunctionFaster (fnc), })

请注意

重要的是要理解这是一个用于基准测试的优化函数。当你做基准测试时,你想要通过所有的测试,比如null, undefined和一些接收到的可能参数。F &&…过滤此null类参数以减少计算时间。

instanceof操作符的注意事项:

此操作符测试构造函数是否存在。对象的原型链中的原型。这通常(虽然不总是)意味着对象是用构造函数构造的。因此,这个过程比typeof操作符慢。

Typeof v === 'function')

typeof操作符的注意事项:

该操作符返回指示操作数值类型的字符串。执行速度非常快。

instanceof和typeof操作符的注意事项:

记住,一个类声明,它也被这些操作符视为一个函数,正如你在这段代码中看到的:

// Class Declaration class A {} // Instances const obj = {} const arr = [] const fnc = () => {} const a = new A() console.log('typeof') console.log(`Object[${typeof Object}], obj[${typeof obj}]`) console.log(`Array[${typeof Array}], arr[${typeof arr}]`) console.log(`Function[${typeof Function}], fnc[${typeof fnc}]`) console.log(`A[${typeof A}], a[${typeof a}]`) console.log('instanceof') console.log(`Object[${Object instanceof Object}], obj[${obj instanceof Object}]`) console.log(`Array[${Array instanceof Array}], arr[${arr instanceof Array}]`) console.log(`Function[${Function instanceof Function}], fnc[${fnc instanceof Function}]`) console.log(`A[${A instanceof A}], a[${a instanceof A}]`)

下面是isFunction和isFunctionFaster在不同实例中的基本示例:

// Functions const isNil = o => o == null const isFunction = f => !!f && f instanceof Function const isFunctionFaster = f => !!f && 'function' === typeof f class A {} function basicFnc(){} async function asyncFnc(){} const arrowFnc = ()=> {} const arrowRFnc = ()=> 1 // Not functions const obj = {} const arr = [] const str = 'function' const bol = true const num = 1 const a = new A() const list = [ isFunction, isFunctionFaster, basicFnc, arrowFnc, arrowRFnc, asyncFnc, Array, Date, Object, Number, String, Symbol, A, obj, arr, str, bol, num, a, null, undefined, ] for (const arg of list) { console.log(`${arg} is a function: ${isFunction(arg)}`) }

下面是这些函数的基本基准:

/** * Figure out how long it takes for a method to execute. * * @param {Function} method to test * @param {number} iterations number of executions. * @param {Array} args to pass in. * @param {T} context the context to call the method in. * @return {number} the time it took, in milliseconds to execute. */ const bench = (method, list, iterations, context) => { let start = 0 const timer = action => { const time = performance.now() switch (action) { case 'start': start = time return 0 case 'stop': const elapsed = time - start start = 0 return elapsed default: return time - start } }; const result = [] timer('start') list = [...list] for (let i = 0; i < iterations; i++) { for (const args of list) { result.push(method.apply(context, args)) } } const elapsed = timer('stop') console.log(`Called method [${method.name}]`) console.log(`Mean: ${elapsed / iterations}`) console.log(`Exec. time: ${elapsed}`) return elapsed } const fnc = () => {} const isFunction = (f) => f && f instanceof Function const isFunctionFaster = (f) => f && 'function' === typeof f class A {} function basicFnc(){} async function asyncFnc(){} const arrowFnc = ()=> {} const arrowRFnc = ()=> 1 // Not functions const obj = {} const arr = [] const str = 'function' const bol = true const num = 1 const a = new A() const list = [ [isFunction], [basicFnc], [arrowFnc], [arrowRFnc], [asyncFnc], [Array], [Date], [Object], [Number], [String], [Symbol], [A], [obj], [arr], [str], [bol], [num], [a], [null], [undefined], ] const e1 = bench(isFunction, list, 10000) const e2 = bench(isFunctionFaster, list, 10000) const rate = e2/e1 const percent = Math.abs(1 - rate)*100 console.log(`[isFunctionFaster] is ${(percent).toFixed(2)}% ${rate < 1 ? 'faster' : 'slower'} than [isFunction]`)

结论

一般来说,isFunctionFaster比isFunction快30%。

我认为你可以在Function原型上定义一个标志,然后检查你想测试的实例是否继承了这个标志

定义一个标志:

Function.prototype.isFunction = true; 

然后检查它是否存在

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

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

我发现在测试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及以下版本并不总是有效。

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