eval 效能不彰已是公開的事實,但有時又似乎非它不可,但 eval 真的是無可取代的嗎?

小弟無意中在某中國網站上發現高手提供兩種 eval 常用方式的替代方法,現公佈在下方:

  1. 使用 eval 解析/ 轉換 JSON 字串的替代方案:
    使用 eval 將 JSON 字串轉成 Object 是常用的方式,雖然目前第三方廠商提供的 Javascript 函式庫都已經包含了解析 JSON 字串的方法,但如果只是很解單的寫個程式又不想使用第三方廠商提供的函式庫時,可以用以下的寫法:

    var jsonObj = (new Function('return ' + JSON 字串))();

    完整的範例:
    function test24(){
        var jsonStr = "{'name':'camus'}";
        var jsonObj = (new Function('return ' + jsonStr))();
        alert(jsonObj.name);
    }
    



  2. 使用 eval 執行字串形態的指令碼替代方案:
    使用 eval 來執行一個字串形態的指令碼也是非常常見的使用方式,替代的方式也不難,就是先在頁面上新增一個 SCRIPT 節點,然後將字串形態的指令用 Script 節點屬性 .text 丟入即可。
    function test25() {
        var script = document.createElement("SCRIPT");
        document.body.appendChild(script);
        script.text = "var a = 1; a++;";
        alert(a);
    }
    


    使用以上的方法時請注意, 在 Firefox 與 Chrome 瀏覽器中,新增出來的 Script 節點只有一次使用 .text 來執行字串形態指令碼的機會,但在 IE 則無此限制,也就是以上的範例若是改成下述:

    function test25() {
        var script = document.createElement("SCRIPT");
        document.body.appendChild(script);
        script.text = "var a = 1; a++;";
        alert(a);
        script.text = "var b = 100; b--;";  // 此行在 Firefox 與 Chrome 中不會被執行
        alert(b);
    }
    


    則在 Firefox 與 Chrome 中,alert(b) 將會出現錯誤, 其主要原因是 script.text = "var b = 100; b--;" 這串指令碼雖然被塞入了 Script 節點中,但是卻沒有被執行。

    因此要跨瀏覽器執行的方式就是每次要執行字串型態指令碼時,先新增一個 Script 節點,等執行完指令後再移除掉。等下一個新的指令碼要執行時再新增一個新的 Script 節點,一樣是執行完就移除,以下為修改後的範例:

    function test25() {
        var script = document.createElement("SCRIPT");
        document.body.appendChild(script);
        script.text = "var a = 1; a++;";
        document.body.removeChild(script);  // 執行完畢後移除 Script 節點
         alert(a);
    
        script = document.createElement("SCRIPT"); // 若要執行下個指令碼,則新增一個新的 Script 節點
        document.body.appendChild(script);
        script.text = "var b = 100; b--;";
        document.body.removeChild(script); // 執行完畢後移除 Script 節點
        alert(b);
        alert(a);
    }
    




以上的參考資料在此篇文章的回應中

創作者介紹
創作者 大笨鳥 的頭像
大笨鳥

大笨鳥的私房菜

大笨鳥 發表在 痞客邦 留言(0) 人氣()