天天看點

JavaScript依賴注入的實作思路

如今各個架構都在子產品化,連前端的javascript也不例外。每個子產品負責一定的功能,子產品與子產品之間又有互相依賴,那麼問題來了:javascript的依賴注入如何實作?(javascript的依賴注入,各大架構都有相應的實作,這裡隻學習實作思路)

JavaScript依賴注入的實作思路

如下需求:

假設已經有定義好的服務子產品key-value集合,func為添加的新服務,參數清單為服務依賴項。

var services = { abc : 123, def : 456, ghi : 789 }; // 假設已定義好某些service 

function service(abc, ghi){ 

    this.write = function(){ 

        console.log(abc); 

        console.log(ghi); 

    } 

function activitor(func){ 

    var obj; 

    // 實作 

    return obj; 

解決思路:

通過某種機制(反射?),取出該func定義的參數清單,并一一指派。然後再通過某種機制(activitor?),執行個體化該func。

解決方案:

一、擷取func的參數清單:

如何擷取參數清單呢?我首先想到的是反射機制。那javascript裡面有沒有反射呢?應該有吧,我目前隻知道使用eval(str)函數,但貌

似并沒有擷取參數清單的相關實作。再看func.arguments定義,此屬性隻在調用func并傳遞參數時才有效,也不能滿足需求。

那能不能通過處理func.tostring()後的字元串擷取參數清單呢?

上手試試吧:

function getfuncparams(func) { 

     var matches = func.tostring().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m); 

     if (matches && matches.length > 1) 

         return matches[1].replace(/\s*/, '').split(','); 

     return []; 

}; 

至此獲得func參數清單數組。

二、根據參數清單尋找依賴:

得到了參數清單,即得到了依賴清單,将依賴項作為參數傳入也就很簡單了。

var params = getfuncparams(func); 

or (var i in params) { 

    params[i] = services[params[i]]; 

三、傳遞依賴項參數并執行個體化:

我們知道,javascript裡面有func.constructor有call(thisarg,[arg[,arg,[arg,

[…]]]])和apply(thisarg,args…)兩個函數,都可以實作執行個體化func操作。其中call函數第一個參數為this指針,剩餘為

參數清單,這個适合在已知func參數清單的情況下使用,不能滿足我的需求。再看第二個apply函數,第一個參數也為this指針,第二個參數為參數數

組,其在調用時會自動為func的參數清單一一指派,正好滿足我的需求。

代碼大概如下:

    var obj = {}; 

    func.apply(obj, params); 

至此我們能夠建立該func的執行個體,并傳遞該func需要的參數。

四、列印測試一下吧:

完整代碼:

var 

    // 假設已定義好某些service 

    services = { abc: 123, def: 456, ghi: 789 }, 

    // 擷取func的參數清單(依賴清單) 

    getfuncparams = function (func) { 

        var matches = func.tostring().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m); 

        if (matches && matches.length > 1) 

            return matches[1].replace(/\s+/, '').split(','); 

        return []; 

    }, 

    // 根據參數清單(依賴清單)填充參數(依賴項) 

    setfuncparams = function (params) { 

        for (var i in params) { 

            params[i] = services[params[i]]; 

        } 

        return params; 

    }; 

// 激活器 

function activitor(func) { 

    func.apply(obj, setfuncparams(getfuncparams(func))); 

// 定義新service 

function service(abc, ghi) { 

    this.write = function () { 

// 執行個體化service并調用方法 

var service = activitor(service); 

service.write(); 

控制台成功列印!

來源:51cto

繼續閱讀