Прежде всего: если вы можете избежать использования eval
, избегайте использования eval
. Ваш код должен вернуться с POST
? Потому что если вы хотите вместо этого использовать GET
, вы можете просто добавить элемент script на страницу:
var script = document.createElement('script');
script.src = "http://example.com" +
"?" + encodeURIComponent("param1name") + "=" + encodeURIComponent("param1value") +
"&" + encodeURIComponent("param1name") + "=" + encodeURIComponent("param2value");
var parent = document.body
|| document.documentElement
|| document.getElementsByTagName('head')[0];
parent.appendChild(script);
Готово.
Или, если это POST
, действительно ли должно быть реальным кодом сценария? Разве это не могут быть данные, которые интерпретируются по коду, уже указанному на странице? JSON - это полезный формат данных, если вы можете пойти по этому пути.
Но если он имеет , чтобы быть POST
, и то, что вы получите , имеет , чтобы быть реальным кодом сценария, а не данными, тогда мы должны будем сделать что-то вроде eval
. : -)
eval
сам по себе очень, очень особенный. Он работает в той области, в которой он используется, даже если он немного похож на функцию, а функции работают не так. Таким образом, на самом деле вычислить код скрипта в глобальной области видимости сложно, если только вызов eval
на самом деле не равен в глобальной области видимости (не в вызове любой функции), и, конечно, вы не можете сделать это здесь & mdash; Вы должны вызвать это из вашего обратного вызова ajax, и поэтому по определению это происходит внутри функции. ( Редактировать : Я только что подумал, как на самом деле использовать eval
в глобальном масштабе, изнутри функции. См. Обновление в конце ответа. Но это зло, ужасно и неправильно.)
Причина, по которой вы, возможно, видели совет, говорящий об использовании window.eval
, заключается в том, что многие современные браузеры предлагают window.eval
(в отличие от eval
), который оценивает данный код в глобальной области видимости. Но это доступно не во всех браузерах, и уж точно не в старых.
Однако есть обходные пути. Семейство IE предоставляет execScript
, что очень аналогично window.eval
, предлагаемому другими браузерами, и в худшем случае вы можете использовать элемент script
. Вот глобальная функция eval, которая работает практически во всем:
window.evalInGlobalScope = (function() {
var fname, scr;
// Get a unique function name
do {
fname = "__eval_in_global_test_" + Math.floor(Math.random() * 100000);
}
while (typeof window[fname] !== 'undefined');
// Create test script
scr = "function " + fname + "() { }";
// Return the first function that works:
return test(evalInGlobalScope_execScript) ||
test(evalInGlobalScope_windowEval) ||
test(evalInGlobalScope_theHardWay) ||
evalInGlobalScope_fail;
function test(f) {
try {
f(scr);
if (typeof window[fname] === 'function') {
return f;
}
}
catch (e) {
return false;
}
finally {
try { delete window[fname]; } catch (e) { window[fname] = undefined; }
}
}
function evalInGlobalScope_execScript(str) {
window.execScript(str);
}
function evalInGlobalScope_windowEval(str) {
window.eval(str);
}
function evalInGlobalScope_theHardWay(str) {
var parent, script, d = document;
parent = d.body || d.documentElement || d.getElementsByTagName('head')[0];
if (parent) {
script = d.createElement('script');
script.appendChild(d.createTextNode(str));
parent.appendChild(script);
}
}
function evalInGlobalScope_fail() {
throw "evalInGlobalScope: Unable to determine how to do global eval in this environment";
}
})();
.. и вот живой пример его использования .
Обратите внимание, что весь код, определяющий, что использовать, запускается только один раз; выбранная функция присваивается свойству evalInGlobalScope
в window
.
Также обратите внимание, что я не дал ему никакого возвращаемого значения. Это связано с тем, что версия «трудным путем» в принципе не может возвращать никакого возвращаемого значения, поэтому безопаснее, если ни один из них не возвращает. Имейте в виду, я не уверен, какие браузеры все еще требуют "трудного пути" & mdash; почти все имеет execScript
и / или window.eval
сейчас.
Обновление : Я сказал выше, что вы не можете использовать eval
в глобальном масштабе изнутри функции. И технически это правда, но я подумал о том, как покончить с этим. Это зло, ужасно и неправильно, но оно работает: используйте вместо него setTimeout
и установите таймаут 0
:
setTimeout("your code here", 0);
Когда вы даете setTimeout
строку, она выполняет eval
над ней & mdash; после таймаута в глобальном масштабе .
Опять же, это зло, ужасно и неправильно, и у него есть дополнительный недостаток - он асинхронный (тогда как с нашей функцией evalInGlobalScope
вычисление происходит синхронно), но это ... вроде ... работает. ( Live copy ) Я не рекомендую.