第一關:如果你能避免使用eval
,避免使用eval
。您的代碼是否有從POST
回來?因爲如果你願意使用GET
相反,你可以在腳本元素只是追加到頁面:
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
調用實際上是在全局範圍(不在任何函數調用中),當然你不能在這裏做到這一點 —你必須從你的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";
}
})();
..和here's a live example of using it。
請注意,所有代碼只能運行一次的代碼;被選中的功能被分配到window
上的evalInGlobalScope
屬性。
另請注意,我沒有給它任何返回值。那是因爲「硬路」版本基本上不能返回任何返回值,所以最安全的是它們都沒有。請注意,我不確定哪些瀏覽器仍然需要「困難的方式」 —現在幾乎所有東西都有execScript
和/或window.eval
。
更新:我上面說你不能在全局範圍內使用eval
在一個函數中。從技術上講,這是真的,但我想到一種方法來解決這個問題。這是邪惡和恐怖的和錯誤的,但它的工作:使用setTimeout
代替,並給它的0
超時:
setTimeout("your code here", 0);
當你給setTimeout
一個字符串,它在超時後執行就可以了 —的eval
,全球範圍內的。
再一次,它是邪惡的,可怕的和錯誤的,它有一個額外的缺點,即它是異步的(而我們的evalInGlobalScope
函數,eval同步發生),但它確實......排序......工作。 (Live copy)我不要推薦它。
實際上,您可以在jsFiddle中成功完成AJAX調用,請參閱此[參考頁](http://doc.jsfiddle.net/use/echo.html)。 –
單詞'I'大寫英文。 –