检查变量是否为函数类型

IT技术 javascript
2021-02-03 17:57:47

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

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

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

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

如何检查变量a是否属于Function上述定义的类型

6个回答
if (typeof v === 'function') {
    // do something
}
@mquandalle 没有太大区别,除非instanceof您正在检查来自另一个文档(可能是 iframe)的函数,否则将不起作用。性能各不相同。
2021-03-12 17:57:47
只需要注意一些东西,比如typeof Object, typeof Date, 和typeof String,它们'function'也会返回
2021-03-16 17:57:47
@Dave,我不确定问题是什么,因为这些是函数。
2021-03-21 17:57:47
与 有if (v instanceOf Function)什么区别
2021-04-06 17:57:47
与接受的答案不同,这也适用于异步函数。对于 an asyncfunctionToCheckgetType.toString.call(functionToCheck)==='[object AsyncFunction]'typeof asyncfunctionToCheck === 'function'
2021-04-10 17:57:47

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

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

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

注意:此解决方案不适用于异步函数、生成器或代理函数。有关更多最新解决方案,请参阅其他答案。

亚历克斯,我很好奇你为什么说 typeof 应该只用于检查未定义。顾名思义,它的目的是检查某物的类型,而不仅仅是它是否存在。使用它进行类型检查时是否存在技术问题或问题,或者更多的是偏好?如果有警告,最好列出它们,这样其他人就可以避免被它们绊倒。
2021-03-22 17:57:47
关于部分:typeof 应该只用于检查变量或属性是否未定义。javascript.info/tutorial/type-detection中的A good use of typeof部分和作者指出的以下部分,情况正好相反
2021-03-26 17:57:47
请继续滚动以找到更简单的解决方案。
2021-03-26 17:57:47
可能有人对此事进行了更广泛的研究,但可以通过简单的“结果验证”查看 jsperf 修订版 4 的结果isFunctionA显示了与其他方法相比的实现差异。
2021-04-01 17:57:47
通过更新的性能测试,似乎根据您的浏览器存在巨大的速度差异。在 Chrome 中typeof(obj) === 'function'似乎是迄今为止最快的;然而,在 Firefox 中obj instanceof Function是明显的赢家。
2021-04-09 17:57:47

有几种方法,所以我将总结它们

  1. 最好的办法是:
    
    function foo(v) {if (v instanceof Function) {/* 做某事 */} };
    
    
    最高效(无字符串比较)和优雅的解决方案 - instanceof 运算符在浏览器中已经被支持很长时间了,所以不用担心 - 它可以在 IE 6 中工作。
  2. 下一个最好的方法是:
    
    function foo(v) {if (typeof v === "function") {/* 做某事 */} };
    
    
    缺点typeof是它很容易出现无声失败,不好,所以如果你有一个错字(例如“finction”) - 在这种情况下,`if` 只会返回 false 并且你不会知道你有错误,直到稍后你的代码
  3. 下一个最好的方法是:
    
    函数 isFunction(functionToCheck) {
        var getType = {};
        return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
    }
    
    
    这与解决方案 #1 或 #2 相比没有优势,但可读性要差得多。这个的改进版本是
    
    函数 isFunction(x) {
        return Object.prototype.toString.call(x) == '[object Function]';
    }
    
    
    但仍然比解决方案#1 少很多语义
关于您关于打字错误的观点:任何有此打字错误的代码都可能很快失败/并不比基于打字错误的任何其他错误更明显。typeof === "function" 是最干净的解决方案。此外,您使用的“最佳”解决方案instanceof不会考虑多个全局变量,例如跨帧检查,并且可能返回假阴性。
2021-03-20 17:57:47
如果函数传递给不同的框架上下文,第一个解决方案就会失败。例如,来自 iframe top.Function !== Function可以肯定的是,使用第二个(希望在调试期间纠正“函数”的任何拼写错误)。
2021-04-02 17:57:47
错字的故事只是为了提到魔法字符串的危害。尽可能避免使用魔法字符串。
2021-04-08 17:57:47

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

Underscore.js 现在使用typeof obj == 'function' || false. 来源
2021-03-13 17:57:47
@PaulRosania 今天早些时候偶然发现了这些性能测试,并通过验证和更多测试数据更新了它们作为修订版 4 - 请运行它以增加浏览器测试覆盖率。它的每秒操作速度较慢(由于进行了许多测试),但它也显示了一个实现差异(打开 javascript 控制台并重新加载页面,可能会记录错误消息)。注意:修订版 3 添加了 isFunctionD(仅基于typeof == "function") - 它似乎比 Underscore 的“快速”版本快得多
2021-03-17 17:57:47
我确实喜欢下划线,简单但功能强大。也就是说,可能值得注意的是,此实现可能会被具有这些属性的对象欺骗。
2021-03-20 17:57:47
Underscore 的版本在大多数浏览器中快得多。请参阅:jsperf.com/alternative-isfunction-implementations
2021-03-27 17:57:47
这个答案现在有点误导,因为 Underscore.js 现在是对替代实现的测试的修订版 12,而不是上面引用的修订版 4 isFunction()它目前使用的东西与dandean建议的非常接近
2021-03-30 17:57:47

jQuery(自 3.3 版起已弃用)参考

$.isFunction(functionName);

AngularJS 参考

angular.isFunction(value);

Lodash 参考

_.isFunction(value);

下划线 参考

_.isFunction(object); 

Node.js从 v4.0.0 开始弃用参考

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