-3

我有以下代码,旨在随时检查函数是否存在。 此代码目前没有任何错误。我使用它是因为我的 javascript 文件以任意顺序加载,并且对于我的项目以这种方式完成是必需的。由于我的 javascript 文件是分开的以便在它们之间运行函数,因此您必须将它们存储在全局变量中,然后从全局变量中调用该函数。

Javascript 文件示例:“checker.js” // 检查函数是否存在

       var funcList = {};
       $(document).ready(function(){
            funcList.requireJS =
            function requireJS(requires,callback){
                console.log("requireJS Starting With Requires Below:");
                console.log(requires);
                var attempts = 0;

                attemptRequire();

                function attemptRequire(){
                    $.each(requires, function (key, value){
                        attempts++;
                        console.log("Checking:"+value+" attempts="+attempts);
                        if (typeof eval(value) !== 'undefined'){
                            callback(); //them run the function
                        }else{
                            console.log("require JS waiting...");
                            setTimeout(function(){attemptRequire();}, 100);//wait and try again every 100 milliseconds.
                        }
                    });
                }

                console.log("requireJS Finished!...");
            };
        });

使用全局函数示例:sample.js

$(document).ready(function(){
    console.log("Quote.Js Loading...");

    requires = {
        0 : "$.fn.mask"
    };

    funcList["requireJS"](requires, function(){
        $("#partone_phone").mask("(999) 999-9999? x99999");
        console.log("Quote.Js Loaded!");
    });

});

这个想法是,如果 jQuery 上的“屏蔽”插件尚未加载,那么它不会尝试运行代码,但一旦加载它就会运行。在未加载插件时尝试运行 .mask 将导致字段没有所需的影响。我以 jquery.mask 为例,但这可能适用于任何事情。

然而,我正在使用 jquery.mask,因为作为一个 jquery 函数,它似乎是引用它的唯一方法是使用 $.fn.mask

通常我可以通过说来测试函数typeof functionNameHere !== 'undefined'并且这有效,但是由于这是一个 jquery 函数,如果我发送字符串 '$.fn.mask' 它就不起作用,除非我在它周围放置一个 eval() ......正如我们都知道是坏形式!

有没有人有更好的选择来使用 eval() 来完成这项工作?

另请注意:

requires = {
        0 : $.fn.mask
    };

尝试不带字符串直接发送函数是行不通的,因为如果它是未定义的,它会在它转到 requireJS 时保持未定义。

4

4 回答 4

2

更好的选择可能是只传递一个要执行的函数,而不是返回您正在寻找的方法或 false。

requires = {
    0 : function () {
        return $ && $.fn && $.fn.mask;
    }
};

现在,您所要做的就是调用requires[0]()以查看是否$.fn.mask已定义。


旁注:将其称为“requireJS”可能会使未来的开发人员感到困惑,因为这不是requireJS,它只是您自己的函数,用于检查脚本是否已完成加载。requireJS 是一个模块加载器,如果你使用它,它可能会减少这个问题。

于 2015-06-03T18:20:15.177 回答
0

一个很好的替代方法是在使用函数之前定义它们。

例如:

function foo() {}

foo()

如果您正在加载脚本,请确保定义插件的标签高于使用它的标签:

<script src="/yet/another/jquery/plugin.js"></script>
<script src="/my/code.js"></script>
于 2015-06-03T18:02:47.797 回答
0

你可以只传递函数本身吗?

由于您正在eval获取传递的名称,因此这些函数位于全局范围内,您对调用它们的上下文几乎没有兴趣。

与其传递名称并假设它们可以访问,不如传递对函数的引用并调用它。它将使您的设计更加灵活。

requires = {
  0 : $.fn.mask
};

if (value() !== 'undefined') {
  callback(); //them run the function

如果您需要控制函数的执行上下文,bind请在传递它们之前使用:

requires = {
  0: $.fn.mask.bind($),
  1: console.log.bind(console)
};

bind方法允许您准备具有给定范围和一些参数的函数。

于 2015-06-03T18:02:55.517 回答
0

好的,最近我接受的答案创建了许多随机的 javascript 错误,这些错误会发生并且它们不会向控制台报告错误。

我制作了一种新算法,它似乎更可靠,但仍然依赖于 eval() ......,但至少它有效。

我并不是说这是一个好的答案,但它确实对我有用,也许它对其他人有用。

 var funcList = {};
    $(document).ready(function(){
    //Because javascript files are loaded asynchronously, use requireJS to ensure javascript is loaded...
    //...for your modules to prevent errors.  To load this function from anyfile use the funcList global var.
    //Helper function to get REAL type since mobile safari has issues
    var toType = function(obj) {
        return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
    }

    funcList.requireJS =
    function requireJS(requires,callback){
        console.log("requireJS Starting With Requires Below****:");
        console.log(requires);
        var attempts = 0;
        var successcount = 0;

        attemptRequire();

        function attemptRequire(){
            successcount = 0;//reset it to 0
            $.each(requires, function (key, value){
                attempts++;
                console.log("Checking*:"+value+" attempts="+attempts);

                var type = '';

                var errorOccured = false;
                try{
                    console.log("trying...");
                    type = toType(eval(value));
                    console.log("type="+type);
                    if(type=="function"){
                        successcount++;
                        attempts--;
                        errorOccured = false;
                    }else{
                        console.log("throwing...");
                        throw "Custom error message: Function is undefined, must be defined as function";
                    }
                }
                catch (err){
                    errorOccured = true;
                    console.log("catching...");
                    console.log("error="+err.message);
                }
                finally {
                    if(errorOccured == true){
                        console.log("JS For "+value+" Not Ready Yet, Trying Again in 100ms");
                        setTimeout(function(){attemptRequire();}, 100);//wait and try again every 100 milliseconds.
                        return false;//exit the entire foreach loop early~
                    }
                }
            });
            //Only call the callback once if all requires came in correctly.
            if(successcount == Object.keys(requires).length){
                console.log("calling callback...");
                callback(); //then run the function
            }
        }

        console.log("End of requireJS Function Call");
    };
    console.log("includes.js loaded");
});

如果需要,可以修改其中的 console.log,它应该可以使用了。在这里调用它是下面的示例。

$(document).ready(function(){
    requires = {
        0 : '$.fn.mask',
        1 : '$.fn.validate',
        2 : 'google.maps.LatLng'
    };

    funcList["requireJS"](requires, function(){
        //code dependent upon mask and validate here!
    });
});
于 2015-06-19T03:50:46.603 回答