JavaScript 的動態執行可能比你想像中還要無孔不入
許多方式都會觸發動態執行,這些動態執行一來是非常地難去做測試,二來是捉摸不定,但除了常見的 eval function 、 script tag 以外,還有其他意想不到的方式會變成動態執行…
JS仔都知道, JavaScript 本身有許多的動態執行的坑,一般人不太會喜歡這種特性,甚至在某些書中直接嚴重警告不該使用這些 function 。
除非在某些你想繞過根本問題 (root cause) ,快速解決當下問題的狀況,不過通常看起來會很 hard code 。
比如眾所皆知的 eval function ,甚至有 don’t be eval (evil) 的俗諺,可以參考 Stack Overflow 的這篇文章 Why is using the JavaScript eval function a bad idea?
- 誤用 eval 可能會被 code injection
- 難以抓蟲 (error 在字串的哪?)
- 效能較差
eval 可以被傳入某字串或字串參數,
以上狀況就如同 innerHtml 被惡意插入其他tag一樣
這裡稍微提一下,雖然 JavaScript 多數時候是 client side 的 program ,但是並不代表這 code injection 不重要,這類的 injection 輕則導致程式 crash,重則成為 XSS 。
竟然身為一個 programmer 就不要 coding 時還抱著使用者出問題只要 refresh 就好了的心態…
除了最顯為人知的 eval 以外, innerHtml 主動加入 script 標籤,以及使用document.createElement('script')
並把 src 指向欲動態執行的位置(例如:常見的 JSONP ),也是常見的動態執行方法,好處是程式體積小,依靠網路或 I/O 動態加載。
最為致命的是,你根本不知道你的 code 竟然做了動態加載。
少見的動態加載如同 setTimeout
系列,這個挺冷門的。
setTimeout(“console.log(‘hello’)”,1000); // 一秒後會印出hello字串
咦? setTimeout
不是傳入 function callback 嗎?
不對欸,不對,你這樣一傳還真的會印出來。
(function(){
setTimeout(‘var gl=20’,1000)
})()
而且你猜這個 function 會發生什麼鳥事?
因為 setTimeout
本身帶的是 callback function ,而你直接宣告 var gl=20
,對於這個 callback 來說是裸露在外頭的,不信你過 1 秒後看看 window.gl
是不是 20 ?
其實,只是想打一篇廢文來分享 setTimeout
這個坑,原本是在 paper 看到時還難以置信(畢竟才疏學淺),其他 setXxxxx 系列的 timer 也會有這問題,可以自行替換成 setInterval 試試看。