把字串當做javascript程式碼執行
字串還能當做javascript程式碼來執行?你能想到哪些方法?
1、setInterval("要執行的字串",500);
window物件的方法既可以傳字串,也可以傳函式。該函式第一個引數傳字串容易引起記憶體洩漏,儘量避免這樣寫。
2、setTimeOut("要執行的字串",500);
window物件的方法既可以傳字串,也可以傳函式。該函式第一個引數傳字串容易引起記憶體洩漏,儘量避免這樣寫。
3、eval("要執行的字串");
4、new Function("要執行的字串");
5、<script>"要執行的字串"</script>
6、es6的import
下面主要說說Javascript的全域性函式eval()和new Function()建構函式。
一、eval()
eval()可以動態解析和執行字串,它直接把字串當做Javascript程式碼執行,eval函式接收一個引數str,如果str不是字串,則直接返回str,否則執行str語句。如果str語句執行結果是一個值,則返回此值,否則返回undefined。
JavaScript規定,如果行首是大括號,一律解釋為語句(即程式碼塊)。如果要解釋為表示式(即物件),必須在大括號前加上圓括號。
eval('{foo: 123}') // 123 eval('({foo: 123})') // {foo: 123}
1、執行作用域
var a = 'global scope'; function b(){ vara = 'local scope' eval('console.log(a)'); //local scope } b();
eval中的程式碼執行時的作用域為當前作用域,它可以訪問到函式中的區域性變數,不能訪問全域性變數。
如果需要,自己可以封裝一個函式,讓eval能訪問全域性。
var myNameSpace = {}; myNameSpace.Eval = function(code){ if(!!(window.attachEvent && !window.opera)){ //ie execScript(code); }else{//not ie window.eval(code); } }
傳遞到eval()中的字串:如果eval()是被直接呼叫的,this指的是當前物件;如果eval()是被間接呼叫的,this就是指全域性物件。eval() 方法可以將字串轉換為JavaScript 程式碼並執行。
//eval()的直接呼叫 eval('...') //eval()的間接呼叫 eval.call(null, '...') window.eval('...') (1, eval)('...') (eval, eval)('...')
2、能否攜帶with表示式
在嚴格模式下,eval解析function的字串中不允許攜帶with(x)表示式。
3、安全性
<script> var a = 1; eval("var a=2;"); //改變了當前域的變數a alert(a); </script>
《高效能Javascript》一書指出,在程式碼中使用eval是很危險的,特別是用它執行第三方的JSON資料(其中可能包含惡意程式碼)時。應該儘可能使用JSON.parse()方法解析字串本身,該方法可以捕捉JSON中的語法錯誤,並允許你傳入一個函式,用來過濾或轉換解析結果。
eval非常耗效能,解析成JS程式碼要耗能,執行時也要耗能。
二、new Function()
new Function(arg1, arg2, ..., argN, function_body);中的引數和函式體都以字串形式傳入。
new Function()可以動態解析和執行字串,它把傳入的字串封裝為anonymous匿名函式並返回,直到呼叫這個返回函式時,才會執行字串所要執行的操作。程式設計中並不經常用到,但有時候應該是很有用的。
1、執行作用域
var a = 'global scope'; function b(){ var a = 'local scope'; (new Function('','console.log(a)'))(); //global scope } b();
new Function中的程式碼執行時的作用域為全域性作用域,不論它在哪個地方被呼叫,它訪問的都是全域性變數a,它無法訪問b函式內的區域性變數。
2、能否攜帶with表示式
在嚴格模式下,new Function()的字串中可以攜帶with(x)表示式,因為new Function產生的是global 作用域下的函式,預設是非嚴格模式。
3、安全性
<script> var a = 1; new Function("var a=3;")(); //不改變當前作用域的變數 alert(a); </script>
三、總結
綜上,可以發現使用new Function()執行字串會好一些,這也就是為什麼很多模板引擎採用new Function(),而沒有用eval()的原因吧。