Как выполнить "eval" без написания "eval" в JavaScript

вот в чем дело, у нас есть большая библиотека JS, которую мы хотим сжать, но Юи компрессора не полностью сжимает код, если он находит утверждение "eval", из страха, что он сломает что-то еще. Это здорово и все, но мы точно знаем, что получает eval'D, поэтому мы не хотим, чтобы он стал консервативным, потому что есть утверждение eval в MooTools JSON.декодировать

Итак, в основном вопрос в том, есть ли какой-либо альтернативный (возможно, творческий) способ написания выражение, которое возвращает функцию eval? Я попробовал несколько, но не кости:

window['eval'](stuff);
window['e'+'val'](stuff);
// stuff runs in the global scope, we need local scope

this['eval'](stuff);
// this.eval is not a function

(new Function( "with(this) { return " + '(' + stuff + ')' + "}"))() 
// global scope again

какие идеи? Thx

7 ответов


Не уверен, понял ли я вас, но вы можете применить функцию к определенной локальной (этой) области:

var x = 5;

var f = new Function('alert(this.x)');

function A(x){
    this.x = x;
    f.apply(this,[]);
}

a = new A(10);

это предупреждает 10 как f применяется с A. Это


Спасибо за все идеи, я закончил просто замену текста в скрипте сборки, который выводит JS, в основном заменяя $EVAL$ на eval, после того, как все было сжато. Я надеялся на чисто JS-способ, но с таким количеством различных реализаций браузера eval, вероятно, лучше просто оставить eval в покое

но основываясь на ответе Димитара и некоторых вознях, вот что я нашел. Похоже, причина, по которой это ['eval'] не было работой, заключается в том, что место где это происходит, в MooTools JSON.декодируйте, также внутри хэша:

var JSON = new Hash({
// snip snip
decode: function(string, secure){
    if ($type(string) != 'string' || !string.length) return null;
    if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\./g, '@').replace(/"[^"\\n\r]*"/g, ''))) return null;

    return this.eval('(' + string + ')'); // Firefox says: TypeError: this.eval is not a function
}

});

однако, если я сохраняю локальную область "верхнего уровня" (весь код, включая mootools, работает внутри анонимной функции), то он работает:

var TOP = this;
var JSON = new Hash({
// snip snip
decode: function(string, secure){
    if ($type(string) != 'string' || !string.length) return null;
    if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\./g, '@').replace(/"[^"\\n\r]*"/g, ''))) return null;

    return TOP.eval('(' + string + ')'); // All good, things run within the desired scope.
}

});

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


может ли рефакторинг eval вызывать некоторую внешнюю функцию прокладки, которая не является частью сжимаемого файла?


Я что-то пропустила?

var noteval = this.eval; // can be defined before the file is loaded
noteval("alert('not eval. at all');");

(function() {
    console.log(this);
    noteval("alert('chavs!');");
}).bind(window)();

(function() {
    console.log(this);
    noteval("alert('crappy parents');");
}).bind(window.parent)();

проверьте это http://www.jsfiddle.net/nGL79/ с рамками как различные области eval.

и специфический для mootools:

window["ev"+"al"].pass("alert('what');")();
this["ev"+"al"].pass("alert('no!');")(); // local scope too?

и

var noteval = window["ev"+"al"].create({
    bind: this
}); 

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


var e = "e";
window[e+"val"](stuff);

Если возможно, вы можете попробовать одну из других библиотек сжатия, так как YUI больше не единственная игра в городе.

вот несколько статей о других доступных инструментах сжатия.

Microsoft и Google, похоже, делают лучшую работу, чем YUI в любом случае.


этот путь нуждается в jQuery.

function NotEval(code, callBack) {
    $.ajax({
        url: 'data:application/javascript;charset=utf-8,' + encodeURIComponent(code),
        cache:true,
        success: function (r) {
            if (typeof callBack === "function") {
                callBack()
            }
        },
        error: function (r) {
            console.log("Eval error");
            console.log(r)
        }
    })
}