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


302

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

我想做这样的事情

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

但这让我

回调不是函数

未定义回调时出错。

Answers:


475
typeof callback === "function"

47
这并不是真正的魔术字符串,因为在ECMA规范中已精确定义了typeof值集。尽管开始时的语法有点愚蠢,但它是完全合理的惯用Javascript。
Ben Zotto

2
@quixoto-理解,我想我的意思是无论如何您仍然需要一个字符串-我宁愿不要有比实际需要更多乱七八糟的文字字符串;因此,这不是测试某物是否为函数的理想选择。
杰森·邦廷

4
是的,“魔术”是一个草率的,糟糕的单词选择-我的意思是“文字字符串”而不是“魔术字符串”。我的错。:)
杰森·邦廷


确保删除函数上的括号,并且仅在if条件中使用函数名称,否则将调用该函数,而不是为true或false。
罗素·施特劳斯

236

当前所有的答案都使用文字字符串,如果可能的话,我宁愿不要在我的代码中使用该字符串-这样做(并提供有价值的语义含义,以便启动):

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

就个人而言,我尝试减少代码中徘徊的字符串数量。


另外,虽然我知道这typeof是一个运算符而不是一个函数,但是使用使它看起来像后者的语法几乎没有什么害处。


7
我应该如何使用此功能?我试过isFunction(not_defined))在哪里not_defined是未定义的函数的名称,并且FireBug返回的not_defined is not defined是正确的,但是您的函数应该返回false并且不会生成错误...
Wookie88

@ Wookie88:从技术上讲,我的答案中说明的函数不会返回错误,而是会发生错误,因为JavaScript解释程序试图解析该符号not_defined以便将其值传递给该符号isFunction(),但无法解析它。无法定义isFunction()解决该问题。
詹森·邦廷

3
@ZacharyYates解决ReferenceError的方法将意味着避免使用对未定义函数的引用。您可以在函数调用中进行类型检查,然后将结果传递给函数。jsfiddle.net/qNaxJ可能不太好,但是至少没有使用任何字符串;)
netiul 2014年

8
或避免使用功能,isFunction而只是做一个(typeof no_function == typeof Function)
netiul 2014年

2
@JasonBunting如果您要变得很挑剔,那么您确实应该使用它, typeof(Function())因为Function是一个函数;但是Array,Object和其他内置原型也是如此(由于缺乏更好的术语)。如果您要检查数组,则不会使用该数组typeof(array) === typeof(Array);例如,typeof(array) === typeof(Array())之所以使用它,是因为如果您保持谨慎和一致,则实际上需要评估该函数。
seanmhanson 2015年

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

需要注意的是回调(本身)的计算结果为false,如果是undefinednull0,或false。与的比较null过于具体。


2
还要注意,如果callback其自身的值为“ false-y”,则其typeof 永远不能为“ function”。
2012年

5
@Joe,但是由于短路,如果回调评估为false,则不会执行该测试。
法比奥·A

3
该解决方案无法正常工作,因为第一个条件将立即引发异常。对于对象的属性,这可能有效:if(obj.callback){...}
Roey

8

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

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

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

我认为是一个很好的答案,您是对的,以上所有方法失败的原因是未定义函数。
Matteo Conta

避免使用未定义的引用很简单-只需引用typeof window.doesthisexist而不是即可doesthisexist。但是,使用所示的eval(这是邪恶的)仅适用于命名函数-不适用于问题中的用例。
AD7six 2013年

请注意,这仅适用于全局范围,而可接受的答案也适用于局部范围函数。
inf3rno

6

JavaScript的新手,我不确定行为是否已更改,但是如果未定义均可能的功能,Jason Bunting(6年前)给出的解决方案将无法正常工作。

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

ReferenceError: possibleFunction is not defined当引擎尝试解析符号possibleFunction时,这将引发错误(如Jason答案的注释中所述)

为避免这种情况,您只能传递要检查的函数名称是否存在。所以

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

这会将变量设置为您要检查的函数,或者将其设置为空对象(如果未定义),从而避免了上述问题。


完全清楚:我的代码不会引发错误,这只是JavaScript解析器执行的。如果您尝试以这种方式使用任何未定义的标识符,也会发生同样的情况。
詹森·邦廷

6

尝试:

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

嗨,不要使用“宽松”比较(==)总是使用“ ===”来比较变量的类型。
Joel Carneiro

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

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

3
一个有点迂腐,并仍然使用一个字符串。怎么if(typeof Function === typeof callback)...样 :)
杰森邦廷

@JasonBunting很好奇,使用字符串文字怎么了?
Bsienn

@Bsienn-正如我说的,这是我的学问,但这就是问题。假设您将代码与字符串文字一起使用,并且typeof由于JavaScript的新的/不同的实现,调用此函数以后会返回不同的内容(也许是“ Function”而不是“ function”),这似乎不太可能一个新的/不同的实现会破坏typeof Function === typeof callback检查,因为它在语义级别上应该是相同的。
杰森·邦廷


4

我可能会做

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

我知道有一个可以接受的答案,但是没有人建议这样做。我不太确定这是否符合惯用语言的描述,但它适用于所有情况。

在较新的JavaScript引擎中,finally可以改为使用a 。


这是一个简洁的捷径!尽管仅测试功能是否存在或已定义(不执行该功能)也无法使用。
Beejor 2015年

确实如此。我假设在该执行点回调是可选的。typeof callback无论如何我通常都会用。
昆汀·恩格尔斯

这就说得通了; 我主要关注问题标题而不是其内容。有时候,我喜欢对大量测试使用try-catch的简单性。在这种情况下,与typeof之类的东西相比,您认为使用它在技术上是否不利吗?还是主要是以更适当/预期的方式做事?
Beejor 2015年

1
如果要测试多种类型,那么异常不是很好。例如,我现在正在处理的项目对一个变量使用了大量类型检查,以查看它是函数,字符串还是其他东西。在这个项目中,我确实需要类型。为此,我使用一个类型数组,并检查accepted_types.indexOf(typeof value) !== -1它是否在类型范围内。在这种情况下,我认为例外是禁止的。
Quentin Engles 2015年

2

尝试这个:

callback instanceof Function

1
不起作用 它仍然会给您错误。在将其发布为答案之前,您应该自己尝试一下。
vbullinger 2012年

我刚刚在Chrome,Firefox和Safari中再次测试的@vbullinger –随处可见。您使用哪种发动机遇到麻烦?
eWolf 2012年

火狐浏览器。您是否测试了未定义回调的情况?
vbullinger 2012年

那是因为您直接引用的是一个未定义的变量,该变量永远都
行不通

3
在作者要求的功能参数上使用时,它确实可以工作。我想ECMAScript可以区分不存在的变量和值为undefined的现有变量的情况。对此有更多了解会很有趣。
eWolf 2012年

2

如果你看一下 @Venkat Sudheer雷迪Aedama提到图书馆,underscorejs的,你可以看到这一点:

_.isFunction = function(obj) {
  return typeof obj == 'function' || false;
};

这只是我的提示,提示答案:>




1

我一直在寻找如何检查是否定义了jQuery函数,但我发现它并不容易。

也许可能需要它;)

if(typeof jQuery.fn.datepicker !== "undefined")

type0f($.datepicker) !== undefiled其他情况相同object
vladkras 2015年

0

如果callback()您不只是在函数中调用一次,则可以初始化参数以供重用:

callback = (typeof callback === "function") ? callback : function(){};

例如:

function something_cool(text, callback) {
    // Initialize arguments
    callback = (typeof callback === "function") ? callback : function(){};

    alert(text);

    if (text==='waitAnotherAJAX') {
        anotherAJAX(callback);
    } else {
        callback();
    }
}

限制是,尽管未定义,它将始终执行回调参数。


0

对于全局函数,您可以使用此函数,而不是eval在答案之一中建议。

var global = (function (){
    return this;
})();

if (typeof(global.f) != "function")
    global.f = function f1_shim (){
        // commonly used by polyfill libs
    };

您也可以使用global.f instanceof Function,但可以使用afaik。的值Function在不同的框架中会有所不同,因此仅适用于单个框架的应用程序。这就是为什么我们通常使用它typeof。请注意,在某些环境中也可能存在异常typeof f,例如,通过MSIE 6-8,某些功能例如alert具有“对象”类型。

通过本地功能,您可以使用已接受答案中的一个。您也可以测试该功能是本地的还是全局的。

if (typeof(f) == "function")
    if (global.f === f)
        console.log("f is a global function");
    else
        console.log("f is a local function");

为了回答这个问题,示例代码对我来说是最新的浏览器,没有错误,所以我不确定这是什么问题:

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

注意:我会使用callback !== undefined代替callback != null,但是它们几乎一样。


0

大多数(如果不是全部)以前的答案都具有调用该函数的副作用

这是最佳做法

你有功能

function myFunction() {
        var x=1;
    }
直接测试的方法

//direct way
        if( (typeof window.myFunction)=='function')
            alert('myFunction is function')
        else
            alert('myFunction is not defined');
使用字符串,因此您只能在一个位置定义函数名称

//byString
        var strFunctionName='myFunction'
        if( (typeof window[strFunctionName])=='function')
            alert(s+' is function');
        else
            alert(s+' is not defined');


0

如果希望重新定义函数,则最好使用按其出现顺序定义的函数变量,因为函数是全局定义的,无论它们出现在何处。

创建一个新函数的示例,该新函数调用相同名称的先前函数:

A=function() {...} // first definition
...
if (typeof A==='function')
   oldA=A;
A=function() {...oldA()...} // new definition


-2

一线解决方案:

function something_cool(text, callback){
    callback && callback();
}

他的示例表明,他希望调用该函数(如果已定义),如果未定义,则什么也不会发生。jsfiddle.net/nh1cxxg6返回falsey / false值的函数仍会被调用。当然,当您希望返回值时,这是行不通的。
Samir Alajmovic

啊,我看错了他的问题。但是,如果回调不是函数,则将导致异常。
Frank Bryce
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.