神奇的eval()與new Function()

原文鏈接:http://imys.net/20151222/eval-with-new-function.html

在需要兼容IE8以下的日子裏,往往需要使用eval()來把後端傳過來的JSON串轉成可操作的JSON對象。直到昨天在翻看jQuery源碼時,才發現jQuery.parseJSON的兼容實現用的是new Function()。馬上Google了相關資料,尋找兩者的區別。

eval

eval接受字符串參數,解析其中的js代碼。如果編譯失敗,會拋出異常,否則執行其中的代碼,計算返回值。

eval('2+2');  // 4

eval('console.log("ok")');  // ok

在實際應用中,通常這樣轉換JSON。

var jsonStr = '{ "age": 20, "name": "jack" }';
eval('(' + jsonStr + ')');

爲什麼要加括號呢?

因爲js中{}通常是表示一個語句塊,eval只會計算語句塊內的值進行返回。加上括號就變成一個整體的表達式。

console.log( eval('{}') );      // undefind
console.log( eval('({})') );    // Object {}

使用eval需要注意執行作用域

var s = 1;
function a() {
    eval('var s=2');
    console.log(s);
}

a();                // 2
console.log(s);     // 1

在局部環境使用eval便會創建局部變量。可以顯示指定eval調用者來改變上下文環境。

var s = 'global';
function a() {
    eval('var s = "local"');
    console.log(s);                 // local
    console.log(eval('s'));         // local
    console.log(window.eval('s'));  // global
}

Function

在之前我對於Function的瞭解只限於**“定義方法的一種非主流方式”**。卻忽略了Function與eval相同的字符串參數特性。

語法:var func = new Function(arg1, arg2, ..., functionBody);

實例:

var add = new Function('a', 'b', 'return a+b;');
console.log( add(2, 3) );    // 5

由於其形參使用字符串的方式表示,也可以使用1個字符串來描述多個形參。

var add = new Function('a, b', 'return a+b;');
console.log( add(2, 3) );    // 5

在轉換JSON的實際應用中,只需要這麼做。

var jsonStr = '{ "age": 20, "name": "jack" }',
    json = (new Function('return ' + jsonStr))();

eval 與 Function 都有着動態編譯js代碼的作用,但是在實際的編程中並不推薦使用。如果可以,請用更好的方法替代。

在一些特殊的運用場合,也有一些合理運用的實踐。比如模板解析等。

那麼爲什麼 jQuery 要用new Function而不用eval呢?
看看老外做的兩者以及原生方法的性能比較:JSON Performance comparison of eval, new Function and JSON

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章