Javascript - создание объекта eval?

Я все еще очень новичок в JavaScript (хотя и не в кодировании), так что не стесняйтесь придираться и придираться ко мне.

Я попытался создать что-то, что будет принимать пользовательский ввод. Если первым символом является восклицательный знак, он попытается создать объект с таким именем и запустить метод «действие» этого объекта. В противном случае он будет относиться к нему как к обычному тексту (на данный момент предупреждение)

<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>

Единственная проблема, которую я замечаю, это операторы eval. Я знаю, что мог бы использовать переключатель/кейс и отказаться от eval вместе или даже создать массив, содержащий имена разрешенных функций, и сравнить ввод с этим массивом до eval, но я уверен, что должен быть лучший способ .

Я просто хочу иметь возможность создавать объект и метод и ничего не обновлять (я считаю, что это одно из основных применений утиной печати?). Возможно ли это без eval? Если нет, есть ли простой способ очистить ввод для строк, чтобы избежать таких вещей, как «!eval(alert('u b haxed'))» или «!a;alert('u b haxed')»?

заранее спасибо


person Community    schedule 03.12.2012    source источник
comment
возможный дубликат конструкции динамического объекта в javascript?   -  person zerkms    schedule 03.12.2012


Ответы (1)


Вы должны использовать eval только один раз, чтобы получить функцию, а затем делать все с ней в переменной.

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;

Если эти конструкторы являются глобальными переменными, вы также можете получить к ним доступ как к свойству объекта window:

var fn = window[ args[0] ];
person Bergi    schedule 03.12.2012
comment
Не следует использовать eval даже один раз, так как args[0] исходит из пользовательского ввода. windows[args[0]] намного безопаснее. - person TwiNight; 03.12.2012
comment
Между этим ответом и комментарием TwiNight я получил именно то, что мне было нужно. Большое спасибо вам двоим. - person ; 03.12.2012
comment
@TwiNight: В общем, нет, поскольку каждый пользователь может вручную запустить вредоносный код в своем браузере. window[args[0]] не будет иметь побочных эффектов, но более ограничен. Зависит от того, что нужно пользователю и насколько он опытен. - person Bergi; 03.12.2012
comment
Верно, но eval вообще обесценивается. - person TwiNight; 03.12.2012
comment
@TwiNight eval далеко не устарела. Единственная проблема с eval заключается в том, что неопытные пользователи часто злоупотребляют им. Существует множество сценариев, в которых использование eval вполне допустимо и при этом не возникает угроз безопасности. Устаревший означает, что они действительно хотят удалить эту функцию из языка, но для обратной совместимости они оставляют ее. Однако есть большая вероятность, что они уберут его в будущей версии. Это не относится к eval. - person Aidiakapi; 14.12.2012
comment
@Aidiakapi: он добавляет к языку слишком много причуд, поэтому, например, он не разрешен в строгом режиме. Везде, где вам нужно разобрать и выполнить код, вы по-прежнему можете использовать конструктор Function. - person Bergi; 14.12.2012
comment
@Bergi Каков ваш источник eval, не работающего в строгом режиме? Из статьи строгого режима MDN я цитирую: eval of strict mode code does not introduce new variables into the surrounding scope. Это не значит, что не позволяет. Фактически, приведенный ниже пример кода показывает, что eval используется в строгом режиме. Это не добавляет причуд к языку. Это просто злоупотребление пользователями. Конструктор Function (очевидно) создает функцию из строки кода. Он не выполняет код. Это зависит от того, как вы его используете, но Function можно так же злоупотреблять, как и eval. - person Aidiakapi; 17.12.2012