Как выполнить “оценку”, не пишущий “оценку” в JavaScript

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

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

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

Какие-либо идеи? Спасибо

7
задан Dónal 21 May 2010 в 08:26
поделиться

6 ответов

Спасибо за все идеи, в итоге я просто заменил текст в скрипте сборки, который выводит 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
ответ дан 7 December 2019 в 07:45
поделиться
var e = "e";
window[e+"val"](stuff);
0
ответ дан 7 December 2019 в 07:45
поделиться

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

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

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

0
ответ дан 7 December 2019 в 07:45
поделиться

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

.
1
ответ дан 7 December 2019 в 07:45
поделиться

Я что-то упускаю?

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/ с кадрами как различные области оценки.

и относится к 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 должна вызываться напрямую, а не через функцию с другим именем хотя

1
ответ дан 7 December 2019 в 07:45
поделиться

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

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

3
ответ дан 7 December 2019 в 07:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: