javascript中eval()函數使用方法

本教程主要重介紹eval()函數的語法與使用方法,及在後面我還補充了eval()解析json數據的相關例子,但願文章能幫助到各位深刻理解eval()使用方法吧。
 

前幾天說到js中儘可能不要使用eval,可是eval究竟是什麼那?今天咱們就說說eval的那點事。
 php

首先看一下本定義:java

定義和用法jquery

eval() 函數可計算某個字符串,並執行其中的的 JavaScript 代碼。ajax

語法express

eval(string)json

 

參數瀏覽器

描述安全

 

string    必需。要計算的字符串,其中含有要計算的 JavaScript 表達式或要執行的語句。   服務器

返回值閉包

經過計算 string 獲得的值(若是有的話)。

說明

該方法只接受原始字符串做爲參數,若是 string 參數不是原始字符串,那麼該方法將不做任何改變地返回。所以請不要爲 eval() 函數傳遞 String 對象來做爲參數。

若是試圖覆蓋 eval 屬性或把 eval() 方法賦予另外一個屬性,並經過該屬性調用它,則 ECMAScript 實現容許拋出一個 EvalError 異常。

拋出

若是參數中沒有合法的表達式和語句,則拋出 SyntaxError 異常。

若是非法調用 eval(),則拋出 EvalError 異常。

若是傳遞給 eval() 的 Javascript 代碼生成了一個異常,eval() 將把該異常傳遞給調用者。

提示和註釋

提示:雖然 eval() 的功能很是強大,但在實際使用中用到它的狀況並很少。

 

實例代碼:

eval函數接收一個參數s,若是s不是字符串,則直接返回s。不然執行s語句。若是s語句執行結果是一個值,則返回此值,不然返回undefined。 
須要特別注意的是對象聲明語法「{}」並不能返回一個值,須要用括號括起來纔會返回值,簡單示例以下:

 代碼以下 複製代碼
var code1='"a" + 2'; //表達式
  
varcode2='{a:2}'; //語句
  
alert(eval(code1)); //->'a2'
  
alert(eval(code2)); //->undefined
  
alert(eval('(' + code2 + ')')); //->[object Object]

eval函數的特色,它老是在調用它的上下文變量空間(也稱爲:包,closure)內執行,不管是變量定義仍是函數定義都是如此


eval做用域

先看這段代碼:

 代碼以下 複製代碼
var x = 1;
(function () {
    eval('var x = 123;');
})();
console.log(x);

這個代碼獲得的是 1 而不是 123
若是想讓 eval 執行的代碼是全局的,那麼有幾種方法。

 代碼以下 複製代碼
var x = 1;
(function () {
    window.eval('var x = 123;');
})();
console.log(x);

這個方法標準瀏覽器均可以獲得 123 而IE6-8則依然是 1

相同的例如

 代碼以下 複製代碼

var arr = [0,0,0,0,0,0];
(function () {
    var arr = [1,1,1,1,1,1];
    var _eval = eval;
    window.eval('arr[0] = 123;');
    eval.call(null, 'arr[1] = 123;');
    _eval('arr[2] = 123;');
    (0,eval)('arr[3] = 123;');
})();
console.log(arr);

0,1 貌似不支持IE8- 2,3 貌似不支持 IE7-
反正歸根結底就是兼容性有問題。

不過還在IE下有個 execScript 很是好使。

 代碼以下 複製代碼

var x = 1;
(function () {
    (!-[1,] ? execScript : eval)('var x = 123;');
})();
console.log(x);

eval不可能在全局空間內執行,這就給開發帶來了很多問題,也看到過不少人爲此鬱悶。 
不過如今偶終於找到了解決辦法,嘿嘿,能夠同時兼容IE和Firefox,方法以下:

 代碼以下 複製代碼
var X2={} //my namespace:)
  
X2.Eval=function(code){
  
if(!!(window.attachEvent && !window.opera)){
  
//ie
  
execScript(code);
  
}else{
  
//not ie
  
window.eval(code);
  
}
  
}

如今若是要想在函數內定義全局代碼,就能夠經過調用X2.eval_r(code)方法。

 代碼以下 複製代碼

var s='global';
  
function demo3(){
  
X2.Eval('var s="local"');
  
}
  
demo3();
  
alert(s); //->'local'


eval解析json

代碼以下:

 代碼以下 複製代碼
var data=" 

root: 

{name:'1',value:'0'}, 
{name:'6101',value:'北京市'}, 
{name:'6102',value:'天津市'}, 
{name:'6103',value:'上海市'}, 
{name:'6104',value:'重慶市'}, 
{name:'6105',value:'渭南市'}, 
{name:'6106',value:'延安市'}, 
{name:'6107',value:'漢中市'}, 
{name:'6108',value:'榆林市'}, 
{name:'6109',value:'安康市'}, 
{name:'6110',value:'商洛市'} 
]
}"; 

 
 
這裏以jquery異步獲取的數據類型——json對象和字符串爲依據,分別介紹兩種方式獲取到的結果處理方式。
 
1.對於服務器返回的JSON字符串,若是jquery異步請求沒作類型說明,或者以字符串方式接受,那麼須要作一次對象化處理,方式不是太麻煩,就是將該字符串放於eval()中執行一次。這種方式也適合以普通javascipt方式獲取json對象,如下舉例說明:
 
var dataObj=eval("("+data+")");//轉換爲json對象
 
爲何要 eval這裏要添加 「("("+data+")");//」呢?
 
緣由在於:eval自己的問題。 因爲json是以」{}」的方式來開始以及結束的,在JS中,它會被當成一個語句塊來處理,因此必須強制性的將它轉換成一種表達式。
 
加上圓括號的目的是迫使eval函數在處理JavaScript代碼的時候強制將 括號內的表達式(expression)轉化爲對象,而不是做爲語 句(statement)來執行。舉一個例子,例如對象字面量{},如若不加外層的括號,那麼eval會將大括號識別爲JavaScript代碼塊的開始 和結束標記,那麼{}將會被認爲是執行了一句空語句。因此下面兩個執行結果是不一樣的:
 
 代碼以下:

 代碼以下 複製代碼
alert(eval("{}"); // return undefined
alert(eval("({})");// return object[Object]

 
 
對於這種寫法,在JS中,能夠處處看到。
 
如: (function()) {}();  作閉包操做時等。
 
代碼以下:

 代碼以下 複製代碼
alert(dataObj.root.length);//輸出root的子對象數量 
$.each(dataObj.root,fucntion(idx,item){ 
if(idx==0){ 
return true; 

//輸出每一個root子對象的名稱和值 
alert("name:"+item.name+",value:"+item.value); 
}) 

 
 
注:對於通常的js生成json對象,只須要將$.each()方法替換爲for語句便可,其餘不變。
 
2.對於服務器返回的JSON字符串,若是jquery異步請求將 type(通常爲這個配置屬性)設爲「json」,或者利 用$.getJSON()方法得到服務器返回,那麼就不須要eval()方法了,由於這時候獲得的結果已是json對象了,只需直接調用該對象便可,這 裏以$.getJSON方法爲例說明數據處理方法: 
 
代碼以下:

 代碼以下 複製代碼
$.getJSON("http://www.111cn.net/",{param:"gaoyusi"},function(data){ 
//此處返回的data已是json對象 
//如下其餘操做同第一種狀況 
$.each(data.root,function(idx,item){ 
if(idx==0){ 
return true;//同countinue,返回false同break 

alert("name:"+item.name+",value:"+item.value); 
}); 
});

 
這裏特別須要注意的是方式1中的eval()方法是動態執行其中字符串(多是js腳本)的,這樣很容易會形成系統的安全問題。因此能夠採用一些規避了eval()的第三方客戶端腳本庫,好比JSON in JavaScript就提供了一個不超過3k的腳本庫。

*eval執行的常見錯誤

---源碼

 代碼以下 複製代碼

console.log("Eval Usage");
var str1_err = "function () {console.log('run fun1')};";
try{
    eval(str1_err);
}catch(e){
    console.log(" Error! eval(str1_err)");
    console.log(e.toString());
}
var str1 = "function fun1() {console.log('run fun1')}; fun1();";
eval(str1);

var str2_err = "{name: 'dzh'}";
var result;
try{
    result = eval(str2_err);
    console.log(result.toString());
    console.log("name: " + result.name);
}catch(e){
    console.log(" Error! eval(str2_err)");
    console.log(e.toString());
}
str2 = "({name: 'dzh'})";
result = eval(str2);
console.log(result.toString());
console.log("name: " + result.name);

---結果

 

Eval Usage
 Error! eval(str1_err)
SyntaxError: Unexpected token (
run fun1
dzh
name: undefined
[object Object]
name: dzh

---分析緣由

1)str1_err說明了定義匿名函數致使的報錯; 遇到空的'()', 會報錯;

2)str2_err說明了對於'{}',引擎解析時會把括號理解爲代碼塊, 而程序原意是一個對象直接量; 因此經常使用的方式是在'{}'外圍加小括號, 那麼eval就先執行求值運算, 它就返回對象.

綜述, 使用eval時, 要考慮引擎是如何理解傳入的字符串代碼.

出處:http://www.111cn.net/wy/js-ajax/64587.htm

相關文章
相關標籤/搜索