Search code examples
javascriptjqueryevaljquery-mask

Is there a better alternative to eval() for my function checking algorithm


I have the following code below designed to check that a function exists at anytime. This code does not have any errors currently. I'm using this because my javascript files load in arbitrary orders and is necessary for my project its done that way. Since my javascript files are separated in order to run functions between them you have to store them in a global variable and then call that function from the global variable.

Example of Javascript File: "checker.js" // This checks if the function exists!

       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!...");
            };
        });

Example of using global function: 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!");
    });

});

The idea is that if the plugin for 'masking' on jQuery has not loaded yet then it will not attempt to run the code but once it is loaded it will. Attempting to run .mask when the plugin is not loaded will cause the fields to not have the affect desired. I'm using jquery.mask as an example, but this could apply to anything.

I'm using jquery.mask however, because as a jquery function it seems the only way to reference it is with $.fn.mask

Typically I can test functions by saying typeof functionNameHere !== 'undefined' and this works, but since this is a jquery function if I send the string '$.fn.mask' it doesn't work unless I put an eval() around it... which as we all know is bad form!

Does anyone have a better alternative to using eval() to make this work?

Also Note:

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

Trying to send the function directly without strings does not work, because if it's undefined it stays undefined by the time it goes to requireJS.


Solution

  • A better alternative may be to just pass a function to be executed instead that returns the method you are looking for or false.

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

    Now, all you have to do is call requires[0]() to see if $.fn.mask is defined.


    Side note: referencing this as "requireJS" might be confusing to future developers since this isn't requireJS, it's just your own function for checking if a script is done loading. requireJS is a module loader that would likely make this problem less of a problem if you used it.