Re: [問題] 關於變數名稱的命名問題
eval()可以把一段字串當成arbitrary js在runtime compile並執行
您要的結果 可以用eval簡單達成
事實上eval可能也是為了類似您這類的需求設計的(這我就不確定瞜)
我們總是被告知"eval is evil"
這是為什麼呢?
1.首先是performace
在你在開啟一個頁面時 你的js會被compiled
呼叫compiler會耗掉資源和時間
而我們目前的browser可以在非常短的時間內compile成千上萬行js
為了幾行東西在compile一次很不符合成本效益
2.第二點是安全性
Douglas Crockford在Good Part裡說
The eval function also compromises the security of your application because
it grants too much authority to
the eval'd text.
以client-side來說 用eval會把許多錯誤隱藏起來而難以debug
舉例來說 把不合法的JSON包在eval中 就可以躲過 JsLint的偵測(難怪他會不爽)
而裡面的錯誤也不會被debugger理解 只是知道裡面有東西出錯了
然而實際上 真的以安全性的角度來說 client-side頂多就break頁面 倒是還好
真的和安全性有關的 是server-side的eval
很多script如php都有eval類似的function 這時候就要非常小心 (雖然超出js範疇)
尤其是user-supplied data from client-side
試想如果你 eval($_POST['username'])
馬上就有嚴重的injection漏洞
3.還有一個問題就是難讀與難以maintain
這應該非常明顯
4.另外有一個問題較少被提到 就是context的問題
eval會繼承caller的context而遭到local variable的汙染
有些人不認為這是個問題 但我想如果你想要執行一段arbitrary js
你可能會想要乾淨點的context
回到我們的問題
eval()的alternatives很多
Stoyan Stefanov 的javascript design patterns中介紹了幾種方法
1.如果是想達成像blockname1 blockname2這種實做 可以考慮採用array
如書中例子
// antipattern
var property = "name";
alert(eval("obj." + property));
// preferred
var property = "name";
alert(obj[property]);
2.在Function的constructor 或是setTimeout的函數中 傳一個string的效果和eval其實是類似
所以也要盡量避免 (事件的inline binding也是)
// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);
// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);
3.
eval裡的var宣告會汙染caller context (如果這不是你的本意的話)
這種時候可以用new Function或是function closure隔絕起來
var jsstring = "var un = 1; console.log(un);";
eval(jsstring); // logs "1"
jsstring = "var deux = 2; console.log(deux);";
new Function(jsstring)(); // logs "2"
jsstring = "var trois = 3; console.log(trois);";
(function () {
eval(jsstring);
}()); // logs "3"
以上un會汙染caller scope而deux和trois不會(也就是說 外面讀不到這兩個變數)
4.最後一點是第3點的反向思考
eval不僅會汙染caller scope 也會被外面影響 (因為共享一個scope)
這時候Function constructor可以解決這問題
比較以下:
(function () {
var local = 1;
eval("local = 3; console.log(local)"); // logs 3
console.log(local); // logs 3
}());
(function () {
var local = 1;
Function("console.log(typeof local);")(); // logs undefined
}());
(這解決了eval的context問題 然而 Douglas Crockford並不推這種方法
因為Function constructor其實就是一種eval 只是對scoping有不同的處理)
以上的想法和例子大部分都出自於Good Part和Javascript Design Patterns
如果各位沒有書的話 可以參考以下網路文章
http://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/
http://devlicio.us/blogs/sergio_pereira/archive/2009/03/31/javascript-avoid-the-evil-eval.aspx
希望對您有幫助~
※ 引述《tas72732002 (蔥頭)》之銘言:
: 想請問一下 可否用迴圈產生不同的變數名稱 例如:
: for(var i=0;i<=10;i++){
: var blockname + i = i ;
: }
: 希望最後的結果是
: blockname1 = 1;
: blockname2 = 2;
: blockname3 = 3;
: 可以這樣命名嗎??
※ 引述《tas72732002 (蔥頭)》之銘言:
: 想請問一下 可否用迴圈產生不同的變數名稱 例如:
: for(var i=0;i<=10;i++){
: var blockname + i = i ;
: }
: 希望最後的結果是
: blockname1 = 1;
: blockname2 = 2;
: blockname3 = 3;
: 可以這樣命名嗎??
※ 引述《tas72732002 (蔥頭)》之銘言:
: 想請問一下 可否用迴圈產生不同的變數名稱 例如:
: for(var i=0;i<=10;i++){
: var blockname + i = i ;
: }
: 希望最後的結果是
: blockname1 = 1;
: blockname2 = 2;
: blockname3 = 3;
: 可以這樣命名嗎??
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 71.104.223.87
※ 編輯: senser 來自: 71.104.223.87 (08/27 17:43)
※ 編輯: senser 來自: 71.104.223.87 (08/27 17:51)
推
08/27 18:43, , 1F
08/27 18:43, 1F
→
08/28 02:13, , 2F
08/28 02:13, 2F
→
08/28 02:14, , 3F
08/28 02:14, 3F
討論串 (同標題文章)
Ajax 近期熱門文章
PTT數位生活區 即時熱門文章
10
18