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