如今各個架構都在子產品化,連前端的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