如何判断 JavaScript 函数是否被定义

344

如何判断 JavaScript 中的函数是否已定义?

我想要做类似于这样的操作:

function something_cool(text, callback) {
    alert(text);
    if( callback != null ) callback();
}

当回调函数未定义时,会出现“callback is not a function”的错误。

24个回答

547
typeof callback === "function"

52
这并不是一个神奇的字符串,因为 typeof 值的集合在 ECMA 规范中被精确定义了。尽管它的语法有些怪异,但这是完全合理的惯用 JavaScript。 - Ben Zotto
2
@quixoto - 我明白,我想我的意思是你仍然需要一个字符串 - 我宁愿不要在我的代码中有更多的字面字符串,除非绝对必要; 因此,这不是我测试某些东西是否为函数的理想方式。 - Jason Bunting
4
是的,“magic”这个词用得不太准确,我想说的是“字面字符串”,而不是“魔法字符串”,我的错。 :) - Jason Bunting
1
JSPerf - http://jsperf.com/comparing-underscore-js-isfunction-with-typeof-function/8 - Chris GW Green
2
请确保在if条件语句中只使用函数名而不是带括号的函数,否则函数将被调用而不是返回true或false。 - Russell Strauss

251

所有当前的答案都使用了字符串字面值,但如果可能的话,我希望在我的代码中不要出现它 - 这种方法则不会(并提供有价值的语义意义):

function isFunction(possibleFunction) {
  return typeof(possibleFunction) === typeof(Function);
}

就我个人而言,在我的代码中,我尽量减少字符串的数量...


此外,虽然我知道typeof是一个操作符而不是函数,但使用让其看起来像函数的语法几乎没有什么危害。


8
我该如何使用这个函数?我已经尝试使用 isFunction(not_defined)),其中 not_defined 是一个未被定义的函数名称,FireBug 返回了 not_defined is not defined,这是正确的,但是你的函数应该返回 false 而不是生成错误... - Wookie88
@JasonBunting 我创建了一个jsfiddle来说明它,希望找到一种方法使其工作,但我就是想不出来:http://jsfiddle.net/zacharyyates/rMVCe/(Chrome 29) - Zachary Yates
3
避免 ReferenceError 的方法是避免使用对可能未定义的函数的引用。你可以在函数调用内部进行类型检查,并将结果传递给函数。这个链接提供了一个示例:http://jsfiddle.net/qNaxJ/ 这样做可能不是很好,但至少没有使用字符串;) - netiul
9
或者避免使用 isFunction 函数,直接使用 (typeof no_function == typeof Function) - netiul
5
如果你要这么挑剔的话,你应该使用 typeof(Function()),因为Function是一个函数;但是Array、Object和其他内置原型(缺乏更好的术语)也是函数。例如,如果你要检查一个数组,你不会使用 typeof(array) === typeof(Array),而是应该使用 typeof(array) === typeof(Array()),因为如果你想要谨慎和一致,你实际上需要评估这个函数。 - seanmhanson
显示剩余5条评论

20
if (callback && typeof(callback) == "function")

注意,如果回调函数是undefined, null, 0, 或者false,那么仅使用callback(不带括号)的值为false。与null进行比较太具体化了。


2
请注意,如果 callback 本身评估为“false-y”值,则它的 typeof 永远不可能是“function”。 - Joe
5
@Joe,但是由于短路行为,如果回调函数评估结果为false,那么该测试将不会被执行。 - Fabio A.
4
这个解决方案行不通,因为第一个条件会立即引发异常。 这个可能行得通,适用于对象属性: 如果(obj.callback){...} - Roey

10

如果变量未定义,那些判断函数是否实现的方法也会失败,因此我们使用了更强大的支持接收字符串的方法:

function isFunctionDefined(functionName) {
    if(eval("typeof(" + functionName + ") == typeof(Function)")) {
        return true;
    }
}

if (isFunctionDefined('myFunction')) {
    myFunction(foo);
}

我认为这是一个好答案,你是正确的,如果函数未定义,则上述所有方法都会失败。 - Matteo Conta
1
避免未定义的引用非常简单 - 只需引用 typeof window.doesthisexist 而不是 doesthisexist。然而,使用 eval(即:邪恶)如所示,只能与命名函数一起使用 - 这在问题的用例中无法工作。 - AD7six
请注意,这仅适用于全局范围,而被接受的答案也适用于本地范围函数。 - inf3rno

10

使用 可选链与函数调用,您可以进行以下操作:

function something_cool(text, callback) {
    alert(text);
    callback?.();
}

如果callback是一个函数,它将被执行。

如果callbacknullundefined,则不会抛出错误,也不会发生任何事情。

然而,如果callback是其他类型的(例如字符串或数字),仍将抛出TypeError。


1
我正在寻找的确切解决方案。 - Hemant Rajpoot

8

我可能会做

try{
    callback();
}catch(e){};

我知道已经有了一个被接受的答案,但是没有人建议这个。我不确定这是否符合习惯用语的描述,但它适用于所有情况。

在较新的JavaScript引擎中可以使用finally来替代。


这是一个很方便的快捷方式!但它不能仅用于测试函数是否存在或定义(而不执行它)。 - Beejor
没错。我假设在执行该回调函数时,它是可选的。不过我通常会使用 typeof callback - Quentin Engles
这很有道理;我更关注问题标题而不是其内容。有时候,我喜欢使用try-catch的简单性,而不是为某些东西编写大量测试。您认为在这种情况下使用它与typeof之类的东西相比存在技术上的劣势吗?还是主要是以更适当/预期的方式处理事情的问题? - Beejor
1
如果您想测试多个类型,那么异常不是很好的选择。例如,我现在正在处理的项目使用了很多类型检查来确定一个变量是函数、字符串还是其他类型。在这个项目中,我真的需要知道各种类型。为此,我使用类型数组,并使用 accepted_types.indexOf(typeof value) !== -1 检查它是否在一系列类型中。在这种情况下,我认为异常会起到限制作用。 - Quentin Engles
例外应该是异常的,不要滥用。 - Jonesopolis

8

尝试:

if (typeof(callback) == 'function')

2
嗨,不要使用“宽松”的比较(==),始终使用'==='来比较变量的类型。 - Joel Carneiro

6

我刚开始学习JavaScript,不确定行为是否有所改变,但是Jason Bunting(6年前)给出的解决方案如果possibleFunction未定义,则无法正常工作。

function isFunction(possibleFunction) {
  return (typeof(possibleFunction) == typeof(Function));
}

如果引擎尝试解析符号possibleFunction(如Jason的答案中所述),则会抛出ReferenceError:possibleFunction未定义的错误。

为避免此行为,您只能传递要检查其是否存在的函数名称。因此,

var possibleFunction = possibleFunction || {};
if (!isFunction(possibleFunction)) return false;

这段代码会将一个变量设为你想要检查的函数,如果没有定义,则设置为空对象,从而避免了上述提到的问题。


要完全清楚:我的代码没有抛出错误,那只是JavaScript解析器在执行。如果您尝试以这种方式使用任何未定义的标识符,同样会发生这种情况。 - Jason Bunting

5
typeof(callback) == "function"

4
function something_cool(text, callback){
    alert(text);
    if(typeof(callback)=='function'){ 
        callback(); 
    };
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接