Как переопределить функцию eval в JavaScript? - PullRequest
9 голосов
/ 02 апреля 2010

Например:

(function() {
      var proxied = window.eval;
      window.eval = function() {
        return proxied.apply(this, arguments);
      };
    })();

Но этот код не работает.

Ответы [ 6 ]

12 голосов
/ 02 апреля 2010

eval это магия. В отличие от «реальной» функции, она может читать и записывать локальные переменные в вызывающей программе:

function foo() {
    var a= 1;
    eval('a+= 1');
    alert(a); // 2
}

Замените это eval на функцию прокси, и у вас возникнет проблема: a+= 1 выполняется в области действия proxied вместо foo. В зависимости от того, что происходит в уклоненном коде, что может привести к потере значений, повреждению локальных, случайных глобальных переменных прокси-сервера и т. Д.

Поэтому невозможно заменить eval на полностью работающий прокси. (Для простых случаев, когда местные жители не нужны, вы можете сойти с рук.)

10 голосов
/ 02 апреля 2010

Вы не можете. (Существует ограниченный способ сделать это, но он довольно ограничен и не поддерживает магию, о которой bobince говорит о .)

eval - это не настоящая функция JavaScript, по крайней мере, в одной крупной реализации (JScript IE, по крайней мере, не через IE7; еще не тестировал новую версию IE8), так что сразу начнете работать в беду, потому что вы не сможете вызвать оригинал через apply (не то, что действительно имеет значение для eval).

Недавняя спецификация ECMAScript 5 специально запрещает переопределение eval в строгом режиме (не то, что вы используете строгий режим там), что заставляет меня подозревать, что очень веские причины для того, чтобы не переопределять его.

5 голосов
/ 20 ноября 2012

Хотя и не переносимый, следующий подход работает в некоторых местах, где он иначе не будет (так как он удовлетворяет требованиям ES5, чтобы A) он был извлечен как Ссылка в MemberExpression, а не как Value и B), он приводит к ' стандартная встроенная функция. '- ES5 # 15.1.2)

(function() {
  var proxied = window.eval
  with({get eval(){ console.log('eval called'); return proxied }}) {
    /* client code */
  }
})()

Это очевидно только в том случае, если вы можете заключить код клиента в оператор with (); хотя во многих ситуациях это не должно быть сложно. Очевидно, что тот же подход может затенять window с другим объектом со всеми его свойствами и с прокси-получателем eval.

Среды, которые не поддерживают оператор get SpiderMonkey, могут использовать ES5 defineProperty. Посмотри на это сам.

2 голосов
/ 02 апреля 2010

Я пробовал это в FireFox 3.6.2, и похоже, что оно работает.

Я набрал это прямо в командной строке FireBug:

var proxied = eval;
eval = function() { alert("ha"); return proxied.apply(this, arguments);};
eval(7);
0 голосов
/ 28 марта 2017

Возможно, я не правильно понял вопрос, но я "переопределил" eval(), создав функцию myEval(), в которой содержится исходный eval(), и выполнил шаги добавления в myEval().

function myEval = function(value){
    //do your stuff here
    //for example
    try {
        value = eval(value)
    } catch (error) {
        console.log(error)
        value = NaN
    }
    return value
}
0 голосов
/ 02 апреля 2010

Мало того, что вы не должны этого делать, но я также думаю, что вы, вероятно, не можете. Во-первых, eval является глобальной функцией и, как таковой, не является членом окна (как вы пытались выше). Во-вторых, как глобальная функция весьма вероятно, что она встроена в виртуальную машину и не может быть перезаписана.

...