Question

I'm still very new to JavaScript (not to coding though), so feel free to nit-pick and moron-map things for me.

I've attempted to create something that will accept user input. If the first character is an exclamation point, it'll attempt to create an object with that name and run the "action" method of that object. Else it'll treat it like regular text (for now an alert)

<script type="text/javascript">
function GetInput(input){

    // Trim the spaces off the beginning and end
    input = input.trim();

    if(input.charAt(0) != "!"){
        // Just some normal text
        alert(input);

        return true;
    }

/* Cut off the exclamation point, replace multiple spaces with one,
 * and get the arguments if any. args[0] = the command. */

    var args = input.substr(1).replace(/\s{2,}/g, " ").split(" ");

// Make sure the function is an object with a method named "action"
    if(eval("typeof "+args[0]+";") === "function"
        && eval("typeof "+args[0]+".prototype.action;") === "function"){

        eval("var command = new "+args[0]+"();");

        command.action(args);
    }else{
        alert('"'+args[0]+'" is not a command.');
    }

    return true;
}
</script>

The only problem I'm noticing with this so far is the eval statements. I know I could use a switch/case and ditch eval all together, or even make an array containing the names of the allowed functions and compare the input with that array prior to eval, but I'm sure there's got to be a better way.

I just want to be able to make the object and method and not update anything (which I believe is one of the major uses of of duck-typing?). Is this possible without eval? If not, is there an easy way to sanitize input for strings to avoid things like "!eval(alert('u b haxed'))" or "!a;alert('u b haxed')"?

Thanks in advance

Was it helpful?

Solution

You should use eval only once to get the function, then do everything with it in a variable.

var args = input.substr(1).split(/\s+/);
var fn = eval(args[0]);
if (typeof fn == 'function' && typeof fn.prototype.action == 'function') {
    var command = new fn();
    command.action(args);
} else {
    alert('"'+args[0]+'" could not be evaluated to a valid command.');
}

return true;

If those constructors are global variables, you also can access them as a property of the window object:

var fn = window[ args[0] ];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top