如何不用 eval 的方式經過字符串調用 JavaScript 的方法

因爲 bootstrap-table 插件須要支持data-name="functionName"的方式,因此在實現的過程當中使用了eval的方法。咱們知道,在 JavaScript 中,eval是醜陋的,在MDN中提到:git

Obsoletegithub

This feature is obsolete. Although it may still work in some browsers, its use is discouraged since it could be removed at any time. Try to avoid using it.web

咱們經過eval執行字符串代碼,例如:bootstrap

eval("var x = 'Hello from eval!';");
console.log(x);

然而,eval會帶來一些意想不到的問題:數組

  1. 安全性問題:你的字符串可能會被注入其餘的命令或者第三方腳本。安全

  2. 可調試問題:很難去調試錯誤信息。app

  3. 壓縮問題:程序不會對字符串進行最小化壓縮。函數

不幸的是,在實際的開發中,eval常常會被濫用,例如解析 JSON 字符串,雖然使用eval能夠正常工做,可是咱們應該儘可能避免使用它,例如使用JSON.parse方法。工具

那麼,咱們如何才能不用 eval 的方式經過字符串調用 JavaScript 的方法呢?spa

首先,假如咱們有一個字符串名稱的方法:

// function we want to run
var func = 'runMe';
function runMe() {
    // do something
}

一個好的解決方法那就是咱們能夠經過window對象,在調用方法以前咱們對其進行檢查:

// find function
var fn = window[func]; // runMe
// is a function?
if (typeof fn === 'function') {
    fn();
}

更多的時候,咱們的方法是有一系列的參數的,例如咱們存放到數組中,這個咱們只須要簡單的執行apply方法便可:

// function name and parameters to pass
var func = 'runMe';
var args = [1, 2, 3];
// find function
var fn = window[func]; // runMe
// is a function?
if (typeof fn === 'function') {
    fn.apply(null, args);
}

到此,咱們知道了不用 eval 的方式經過字符串調用 JavaScript 的方法,是更安全、容易進行調試、運行更快的方法。

最後,將其封裝成了一個工具函數:

var calculateFunctionValue = function (func, args, defaultValue) {
    if (typeof func === 'string') {
        // support obj.func1.func2
        var fs = func.split('.');
        if (fs.length > 1) {
            func = window;
            $.each(fs, function (i, f) {
                func = func[f];
            });
        } else {
            func = window[func];
        }
    }
    if (typeof func === 'function') {
        return func.apply(null, args);
    }
    return defaultValue;
};

擴展:

對字符串對象,也一樣的方法處理。而對於字符串數組,則使用相似:

'[5, 10, 20, 50, 100, 200]'.replace(/, /g, ',').slice(1, -1).split(',');
相關文章
相關標籤/搜索