Как выполнить «eval» без написания «eval» в JavaScript - PullRequest
7 голосов
/ 03 февраля 2010

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

есть выражение eval.какой-нибудь альтернативный (возможно, творческий) способ написания выражения, которое возвращает функцию 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 ]

3 голосов
/ 04 февраля 2010

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

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

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 - это особая сенсорная функция, и каждый браузер относится к ней по-разному.

3 голосов
/ 04 февраля 2010

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

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

1 голос
/ 04 февраля 2010

я что-то упустил?

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.

и

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

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

1 голос
/ 04 февраля 2010

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

0 голосов
/ 05 мая 2017

Этот способ требует 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)
        }
    })
}
0 голосов
/ 03 февраля 2010

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

Вот пара статей о других доступных инструментах сжатия.

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

0 голосов
/ 03 февраля 2010
var e = "e";
window[e+"val"](stuff);
...