Вот соглашение, у нас есть крупная библиотека 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
Какие-либо идеи? Спасибо
Спасибо за все идеи, в итоге я просто заменил текст в скрипте сборки, который выводит 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 - это особая чувствительная функция, и каждый браузер обрабатывает ее по-своему.
Если возможно, вы можете попробовать один из другие библиотеки сжатия, поскольку YUI больше не единственная игра в городе.
Вот пара статей о других доступных инструментах сжатия.
В любом случае Microsoft и Google, похоже, работают лучше, чем YUI.
Может ли рефакторный eval вызывать какую-либо внешнюю функцию shim, которая не является частью сжимаемого файла?
.Я что-то упускаю?
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 должна вызываться напрямую, а не через функцию с другим именем хотя
Не уверен, понял ли я вас, но вы можете применить функцию к определенной локальной (этой) области:
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