1. 程式人生 > 其它 >把字串當做javascript程式碼執行

把字串當做javascript程式碼執行

本篇文章介紹6種把字串解析成js程式碼並執行的方法,主要區別eval和new Function。

字串還能當做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(){
 var
a = '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()的原因吧。