假设我有任何变量,定义如下:
var a = function() {/* Statements */};
我想要一个可以检查变量类型是否类似于函数的函数。即:
function foo(v) {if (v is function type?) {/* do something */}};
foo(a);
如何检查变量a
是否为Function
上述定义的类型?
假设我有任何变量,定义如下:
var a = function() {/* Statements */};
我想要一个可以检查变量类型是否类似于函数的函数。即:
function foo(v) {if (v is function type?) {/* do something */}};
foo(a);
如何检查变量a
是否为Function
上述定义的类型?
Answers:
当然,下划线的方法效率更高,但是当效率不是问题时,最好的检查方法是写在@Paul Rosania链接的下划线页面上。
受下划线启发,最终的isFunction函数如下:
function isFunction(functionToCheck) {
return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}
isFunctionA
显示了与其他方法相比的实现差异。
if (typeof v === "function") {
// do something
}
typeof Object
,typeof Date
和typeof String
,而这一切的回报'function'
了。
if (v instanceOf Function)
?
instanceof
如果您正在检查来自另一个文档(可能是iframe)的功能,则不会起作用。性能各不相同。
asyncfunctionToCheck
, getType.toString.call(functionToCheck)==='[object AsyncFunction]'
如typeof asyncfunctionToCheck === 'function'
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
typof
呢?
typeof == "function"
)-它似乎比Underscore的“快速”版本快得多。
有几种方法,所以我将全部总结
函数foo(v){if(v instanceof Function){/ *做某事* /}};性能最佳(无字符串比较)和优雅的解决方案-很长时间以来,浏览器就一直支持instanceof运算符,因此请放心-它可以在IE 6中运行。
函数foo(v){if(typeof v ===“ function”){/ *做某事* /}};的缺点
typeof
是它很容易出现无声故障,很糟糕,因此,如果您有错字(例如“ finction”),在这种情况下,如果if会返回false,直到稍后才会知道您有错误。您的代码
函数isFunction(functionToCheck){ var getType = {}; 返回functionToCheck && getType.toString.call(functionToCheck)==='[对象函数]'; }与解决方案1或解决方案2相比,这没有优势,但可读性差很多。对此的改进版本是
函数isFunction(x){ return Object.prototype.toString.call(x)=='[对象功能]'; }但语义仍然比解决方案#1少很多
top.Function !== Function
。可以肯定的是,请使用第二种方法(希望在调试过程中纠正“功能”的任何拼写错误)。
instanceof
不考虑多个全局变量(例如跨帧检查),并且可能返回假阴性。
尝试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
具有更多浏览器支持并且还包括异步功能的功能可能是:
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
另一种简单的方法:
var fn = function () {}
if (fn.constructor === Function) {
// true
} else {
// false
}
fn && fn.constructor === Function
这个怎么样?
对于那些对功能样式感兴趣或希望在元编程中使用更具表现力的方法(例如类型检查)的人来说,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 ));
但是,请注意,由于广泛使用了高阶函数,因此该解决方案的性能可能比其他可用选项低。
如果你使用Lodash你可以做到这一点_.isFunction。
_.isFunction(function(){});
// => true
_.isFunction(/abc/);
// => false
_.isFunction(true);
// => false
_.isFunction(null);
// => false
true
如果value是一个函数,则返回此方法,否则返回false
。
以下似乎也对我有用(从测试node.js
):
var isFunction = function(o) {
return Function.prototype.isPrototypeOf(o);
};
console.log(isFunction(function(){})); // true
console.log(isFunction({})); // false
我认为您可以在Function原型上定义一个标志,并检查您要测试的实例是否继承了该标志
定义一个标志:
Function.prototype.isFunction = true;
然后检查它是否存在
var foo = function(){};
foo.isFunction; // will return true
缺点是另一个原型可以定义相同的标志,因此毫无用处,但是如果您完全控制包含的模块,这是最简单的方法
您应该在js中使用typeOf
运算符。
var a=function(){
alert("fun a");
}
alert(typeof a);// alerts "function"