【问题标题】:How to tell if a JavaScript function is defined如何判断 JavaScript 函数是否已定义
【发布时间】:2010-09-10 07:01:04
【问题描述】:

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

我想做这样的事情

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

但它给了我一个

回调不是函数

未定义回调时出错。

【问题讨论】:

    标签: javascript reflection


    【解决方案1】:

    我宁愿建议以下功能:

    function isFunction(name) {
        return eval(`typeof ${name} === typeof Function`);
    }
    

    【讨论】:

    • 该问题要求一种方法来确定变量是否是函数,而不是作为函数名称的字符串。
    【解决方案2】:

    这对我有用

    if( cb && typeof( eval( cb ) ) === "function" ){
        eval( cb + "()" );
    }
    

    【讨论】:

      【解决方案3】:

      如果你想重新定义函数,最好使用函数变量,这些变量是按照它们出现的顺序定义的,因为函数是全局定义的,不管它们出现在哪里。

      创建一个调用之前同名函数的新函数示例:

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

      【讨论】:

        【解决方案4】:

        如果不是所有以前的答案,大多数(如果不是全部)都会对调用函数产生副作用

        最佳实践

        你有功能

        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');

        【讨论】:

        • 不确定为什么这里有“窗口”。可能存在范围差异:只需执行 typeof(myFunction) === 'function'
        【解决方案5】:

        我可能会这样做

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

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

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

        【讨论】:

        • 这是一个简洁的快捷方式!虽然它不适用于单独测试函数是否存在或已定义(不执行它)。
        • 确实如此。我假设回调在该执行点是可选的。无论如何,我通常使用typeof callback
        • 有道理;我更关注问题的标题而不是其内容。有时我喜欢在大量测试中使用 try-catch 的简单性。您是否认为使用它有技术劣势,在这种情况下与 typeof 之类的东西相比?还是主要是以更恰当/预期的方式做事?
        • 如果你想测试多种类型,那么异常就不那么好了。例如,我现在正在处理的项目对一个变量进行了大量类型检查,以查看它是函数、字符串还是其他什么。在这个项目中,我真的需要类型。为此,我使用了一个类型数组,并检查accepted_types.indexOf(typeof value) !== -1 以查看它是否在一系列类型中。在这种情况下,我认为例外情况会令人望而却步。
        【解决方案6】:

        试试:

        if (!(typeof(callback)=='undefined')) {...}
        

        【讨论】:

          【解决方案7】:

          试试:

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

          【讨论】:

          • 你好,不要使用“松散”比较(==)总是使用'​​==='来比较变量的类型。
          【解决方案8】:

          对于全局函数,您可以使用这个而不是答案之一中建议的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,但是我不知道。 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,但它们的作用几乎相同。

          【讨论】:

            【解决方案9】:

            如果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();
                }
            }
            

            限制是它总是会执行回调参数,尽管它是未定义的。

            【讨论】:

              【解决方案10】:
              typeof(callback) == "function"
              

              【讨论】:

                【解决方案11】:
                typeof callback === "function"
                

                【讨论】:

                • 这并不是一个真正的魔法字符串,因为 typeof 值的集合在 ECMA 规范中精确定义。虽然它的语法一开始有点傻,但它是完全合理的地道 Javascript。
                • @quixoto - 明白,我想我的意思是无论如何你仍然需要一个字符串 - 我宁愿没有更多的文字字符串乱扔我的代码而不是绝对需要;因此,这不是我测试某个东西是否是函数的理想选择。
                • 是的,“magic”是一个草率、糟糕的词选择——我的意思是“literal string”而不是“magic string”。我的错。 :)
                • JSPerf - jsperf.com/…
                • 确保删除函数上的括号,并且只在 if 条件中使用函数名称,否则将调用函数而不是给你 true 或 false。
                【解决方案12】:

                如果你查看@Venkat Sudheer Reddy Aedama 提到的库的source,下划线js,你可以看到:

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

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

                【讨论】:

                  【解决方案13】:

                  一线解决方案:

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

                  【讨论】:

                  • 他的示例表明,如果函数已定义,他希望调用该函数,如果未定义,则什么也不会发生。 jsfiddle.net/nh1cxxg6 返回 false/false 值的函数仍会被调用。当然,这不适用于您希望返回值的情况。
                  • 啊,我看错了他的问题。但是,如果回调不是函数,这将导致异常。
                  【解决方案14】:

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

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

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


                  另外,虽然我知道typeof 是一个运算符而不是一个函数,但使用使其显示为后者的语法并没有什么坏处。

                  【讨论】:

                  • 我应该如何使用这个功能?我试过isFunction(not_defined)),其中not_defined是未定义的函数名称,FireBug返回not_defined is not defined,这是正确的,但你的函数应该返回false并且不会产生错误......
                  • @Wookie88:从技术上讲,我的答案中说明的函数不会返回错误,而是发生错误,因为 JavaScript 解释器试图解析符号 not_defined 以传递它值isFunction() 并且无法解决它。对isFunction()的定义无能为力解决这个问题。
                  • @ZacharyYates 解决 ReferenceError 的方法意味着避免使用对可能未定义函数的引用。您可以在函数调用中进行类型检查并将结果传递给函数。 jsfiddle.net/qNaxJ 可能不太好,但至少没有使用字符串 ;)
                  • 或者避免使用isFunction 的功能而只使用(typeof no_function == typeof Function)
                  • @JasonBunting 如果你要那么挑剔,你真的应该使用typeof(Function()),因为 Function 是一个函数;但 Array、Object 和其他内置原型也是如此(因为没有更好的术语)。例如,如果您正在检查数组,则不会使用 typeof(array) === typeof(Array);你会使用typeof(array) === typeof(Array()),因为如果你小心且一致,你实际上需要评估函数。
                  【解决方案15】:

                  我一直在寻找如何检查是否定义了 jQuery 函数,但我没有找到它。

                  也许可能需要它;)

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

                  【讨论】:

                  • type0f($.datepicker) !== undefiled 相同,否则为object
                  【解决方案16】:

                  如果你使用http://underscorejs.org,你有: http://underscorejs.org/#isFunction

                  _.isFunction(callback);
                  

                  【讨论】:

                    【解决方案17】:

                    JavaScript 新手我不确定行为是否发生了变化,但如果未定义可能的函数,Jason Bunting(6 年前)给出的解决方案将不起作用。

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

                    当引擎尝试解析符号 possibleFunction 时,这将引发 ReferenceError: possibleFunction is not defined 错误(如 Jason 的回答中提到的 cmets)

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

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

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

                    【讨论】:

                    • 完全清楚:我的代码不会抛出错误,这只是 JavaScript 解析器在做的。如果您尝试以这种方式使用任何未定义的标识符,也会发生同样的情况。
                    【解决方案18】:

                    试试这个:

                    callback instanceof Function
                    

                    【讨论】:

                    • 不起作用。它仍然会给你错误。在将其作为答案发布之前,您应该自己尝试一下。
                    • @vbullinger 我刚刚在 Chrome、Firefox 和 Safari 中再次进行了测试——在任何地方都可以使用。您在哪个引擎上遇到过问题?
                    • 火狐。未定义回调时,您是否测试了案例?
                    • 那是因为你直接引用了一个未定义的变量,它永远不会起作用:pastebin.com/UQz2AmzH
                    • 它在用于函数参数时确实有效,这是作者要求的——我想 ECMAScript 区分了不存在变量和值为 undefined 的现有变量的情况。了解更多这方面的信息会很有趣。
                    【解决方案19】:
                    if (callback && typeof(callback) == "function")
                    

                    请注意,如果是 undefinednull0false,回调(单独)的计算结果为 false。与null 相比过于具体。

                    【讨论】:

                    • 另请注意,如果callback 本身的计算结果为“false-y”值,则其 typeof永远不会为“function”。
                    • @Joe,但由于短路,如果回调计算结果为 false,则不会执行该测试。
                    • 此解决方案不起作用,因为第一个条件将立即引发异常。这可能适用于对象的属性: if (obj.callback){...}
                    【解决方案20】:

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

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

                    【讨论】:

                    • 我认为是一个很好的答案,你是对的,上面所有的方法都失败了是函数没有定义。
                    • 避免未定义的引用很简单——只需引用typeof window.doesthisexist 而不是doesthisexist。但是,如图所示使用 eval(which: is evil)仅适用于命名函数 - 这不适用于问题中的用例。
                    • 请注意,这仅适用于全局范围,而接受的答案也适用于本地范围函数。
                    【解决方案21】:
                    if ('function' === typeof callback) ...
                    

                    【讨论】:

                    • 一个 bit 迂腐的,仍然使用字符串文字。 if(typeof Function === typeof callback)... 怎么样? :)
                    • @JasonBunting 好奇,使用字符串文字有什么问题?
                    • @Bsienn - 正如我所说,这是我的迂腐,但这就是问题所在。假设您使用带有字符串文字的代码,并且对 typeof 的调用稍后会返回不同的内容(可能是“函数”而不是“函数”),因为 JavaScript 的新/不同实现 - 它 feels 新的/不同的实现不太可能破坏typeof Function === typeof callback 检查,因为它在语义级别应该是相同的。
                    【解决方案22】:
                    function something_cool(text, callback){
                        alert(text);
                        if(typeof(callback)=='function'){ 
                            callback(); 
                        };
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 2012-06-09
                      • 2011-08-17
                      • 2019-05-02
                      • 2017-08-16
                      • 2012-01-30
                      • 1970-01-01
                      • 2013-03-30
                      • 2014-04-29
                      • 1970-01-01
                      相关资源
                      最近更新 更多