среда, 25 марта 2015 г.

eval в JavaScript

eval в JavaScript с отложенным выполнением:

var JsEvaluator = (function(){
  var errors = {
    WRONG_SYNTAX : "Синтаксическая ошибка в выражении \"%SOURCE%\"",
    NON_SYNTAX : "Ошибка %ERROR_TITLE% при разборе выражения \"%SOURCE%\""
  };

  function null_func() { return null; }

  return {
    checkedEval : function(str_to_eval){
      if(!str_to_eval)
        return null_func;
      var trimmed_str = str_to_eval.trim();
      if(!trimmed_str)
        return null_func;
      try {
        var result = eval(trimmed_str);
        if(result === undefined)
          return null_func;
      } catch(e) {
        var error_text = (!(e instanceof SyntaxError)) ?
                          errors.WRONG_SYNTAX.replace(/%SOURCE%/, trimmed_str) :
                          errors.NON_SYNTAX.replace(/%ERROR_TITLE%/, e.name).replace(/%SOURCE%/, trimmed_str);
        console.error(error_text);
        return null_func;
      }
      return function() { return eval(trimmed_str); };
    }
  };
})();

Возвращать именно функцию может быть полезно, если выражение в eval завязано на какую-то внешнюю переменную. Например, в str_to_eval у нас условие: "Param1 > 10". Понятно, что его надо выполнить в момент проверки, а не инициализации. Поэтому выполнение в примере отложено.

Для eval выполняется правило последней строки, пришедшее в Ruby и R из Fortran - eval возвращает значение, которое вернула последняя выполненная строка переданного ему выражения. Это может быть в т.ч. строка с числом:
eval("1;2;4")
> 4

или даже со строковой константой:

eval("'boo'")
> "boo"

Как вариант, можно отказаться от ошибок и понимать "неправильный" JavaScript как строковую константу:

var JsEvaluator = (function(){
  function null_func() { return null; }
  return {
    checkedEval : function(str_to_eval){
      if(!str_to_eval)
        return null_func;
      var trimmed_str = str_to_eval.trim();
      if(!trimmed_str)
        return null_func;
      try {
        var result = eval(trimmed_str);
        if(result === undefined)
          return null_func;
      } catch(e) {
        return function() { return str_to_eval; };
      }
      return function() { return eval(trimmed_str); };
    }
  };
})();

Комментариев нет:

Отправить комментарий