前些日子用到了eval()處理json數據,習慣於每次添加'('+json+')'處理數據,也沒去深究為什麼這麼做,剛好同事問我這個問題,瞬間啞口無言,只會如何操作,卻講不出原因,這不符合咱程式員嚴謹的工作態度,仔細思考了一會,簡略的談談吧。 可能會隨時腦洞,望各位見諒。 1.什麼是json? JS ...
前些日子用到了eval()處理json數據,習慣於每次添加'('+json+')'處理數據,也沒去深究為什麼這麼做,剛好同事問我這個問題,瞬間啞口無言,只會如何操作,卻講不出原因,這不符合咱程式員嚴謹的工作態度,仔細思考了一會,簡略的談談吧。
可能會隨時腦洞,望各位見諒。
1.什麼是json?
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式,是一種取代XML的數據結構,和xml相比,它更小巧但描述能力卻不差,由於它的小巧所以網路傳輸數據將減少更多流量從而加快速度。
- JSON就是一串字元串 只不過元素會使用特定的符號標註,其書寫格式是:名稱/值對。
{"name":"json"}
- {} 雙括弧表示對象
- [] 中括弧表示數組
- "" 雙引號內是屬性或值
現在還有很多人存在一些誤區,為什麼{name:'json'}在檢驗時通過不了,
那是因為JSON官網最新規範規定
如果是字元串,那不管是鍵或值最好都用雙引號引起來,所以上面的代碼就是 {"name":"json"}
不要反駁,官網就是這麼定義的。
- : 冒號表示後者是前者的值(這個值可以是字元串、數字、也可以是另一個數組或對象);
2. 如何解析json?
如果從後臺接收json數據時,jquery將type設為'json',或者利用$.getJSON()獲取,此時接收到的json是對象格式,不需要特殊處理,可直接使用;
但是如果接收的json格式是字元串類型,這時就需要將其轉換成對象格式了,兩種方法:eval() 和 new Function();
-
eval
var json='{"name":"lee","age":"15"}' str=window.eval('('+ json+')');
結果如圖:
我們可以看出解析後的json數據格式為對象,方便我們的後續操作處理,但是,我們為什麼要用'('+json+')'這樣的處理呢?
個人拙見如下:首先eval 可將字元串解析為
-
- 具體的對象
- 求表達式的值
- 執行語句
- 求值
- 處理日期數據
還記得json的格式嗎?以"{"開頭對吧,在此那麼你還記的語句塊的格式嗎?也是以"{"開頭是吧,那麼問題就來了,eval解析時會把我們的json當成語句塊,而且這個所謂的語句塊里還有":",那麼極有可能會報錯,如圖:
在此隨便扯一點別的知識點。。
表達式與語句
表達式:表達式,是由數字、算符、數字分組符號(括弧)、自由變數和約束變數等以能求得數值的有意義排列方法所得的組合。約束變數在表達式中已被指定數值,而自由變數則可以在表達式之外另行指定數值。
語句:JavaScript 語句向瀏覽器發出的命令。語句的作用是告訴瀏覽器該做什麼。通常我們在每條可執行的語句結尾添加分號以分隔 JavaScript 語句,多條語句構成語句塊。
有些時候,表達式和語句會看不出區別,但其作用做不同,即有一些表達式會出現在語句的上下文中,為瞭解決歧義,JavaScript語法禁止表達式以大括弧"{"或關鍵字"function"開頭,如果要以"{"開頭的表達式能被正確解析,需要把這個"{}"包裹的內容放在"()"中,確保表達式被解析在表達式上下文中,如果表達式被解析在表達式上下文中,此時json解析後會轉換成對象類型,這就是我們想要的結果。
表達式與語句的交集:
好了,原理講解完成,那麼各位應該明白以'('+json+')'格式處理eval接收數據的原理了吧,如果實在不明白,那就偷個懶,每次都不加'('+json+')',報錯了再加上,時間長了也就能明白了(千萬別聽我的,我開玩笑的%>_<%)。
但是,but,各位有沒有聽過前輩們講過一段話:
對於eval,要理解它,遠離它。
為什麼呢?
- 容易受XSS攻擊 傳送門:http://baike.baidu.com/link?url=FRg1lsOHCUrEjEPp8l2es-TYxk3ZfZR4xNisB_OOvttwL1RyMw0D0M9cuXD78ewFy6exKbP_FMkmIcZgnoP62K
- 調試不方便
- 全局變數污染
- 代碼執行更緩慢
為什麼執行會緩慢呢? 這就要引出另一位主角了:new Function();
2.new Function
先扯些別的,定義函數有三種方式,分別為
- 函數聲明 function fn( arg ) {}
- 函數表達式 var fn=function( arg ) {};
- new var fn=new Function(arg1,arg2...argn,body); ps:此處的arg參數必須是字元串形式,body為函數體,同樣為字元串形式
來看代碼:
//1.取最大值 var getMax=new Function('Math.max(arguments)'); var max=getMax(1,4,5);
//2.處理json數據 var json='{"name":"json","age":"18"}'; data=(new Function('','return'+json))(); console.log(data);
結果如圖:
我們再來看看所謂的代碼執行緩慢的問題是什麼,直接上代碼解釋:
// 1.eval function evalFun (){ var start= (new Date).getTime(); var func=eval('(function(a,b,c,d,e,f,g){return a*b*c*d*e*f*g;})'); var result= func(4234,3424,4234,4324,423,34234,53453); console.log(result); var time= (new Date).getTime()-start; return time; } // 2.new Function function newFun (){ var start= (new Date).getTime(); var func=new Function(['a','b','c','d','e','f','g'],'return a*b*c*d*e*f*g;'); var result=func(4234,3424,4234,4324,423,34234,53453); console.log(result); var time= (new Date).getTime()-start; return time; } t1=evalFun();//輸出處理時間差,單位ms t2=newFun(); console.log('時間比(new Function/eval):'+ t2/t1); //兩者時間對比
兩種方法所處理數據相同,結果相同,請看時間比:
結果清晰明瞭,差別很大是吧,各位看官,您看懂了吧。
最後:鄙人才疏學淺,在此獻醜了,望各位前輩批評指正,在此感謝!------(未完待續) 2016-04-05