首先咱們用大白話來理解一次,依賴注入就是我有一個東西,我平時不用,我把這個東西放在你那裏,在我用的時候你拿給我。數組
這個時候咱們已經初步有了概念,咱們在用代碼來消化這個概念bash
首先咱們來先建立一個inject的對象,對象下有個三個屬性分別爲app
const inject = {
dependencies: {},
register: function(key, value) {
this.dependencies[key] = value;
},
resolve: function(deps, func, scope){
let arr = [];
for (let i = 0 ; i < deps.length ; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
return function(){
func.apply(scope||{},arr);
}
},
}複製代碼
嗯, 大概就是這個,即然已經把初步的想法實現,咱們如今就來試試到底可不能夠注入首先實現我有一個東西,而且把這個東西存在你那,那麼咱們用register方法來註冊兩個函數
inject.register('$http', {
'get': function() {
return '我是依賴注入的$http下的一個函數';
}
});
inject.register('$scope', {
'test': ''
});複製代碼
這個時候我須要用到我前面存放在你那裏東西,你得拿給我ui
let MyController = function($scope,$http){
console.log(`MyController-result:${$http.get()}`)
}
MyController = inject.resolve(['$scope','$http'],MyController)
MyController(); // MyController-result:我是依賴注入的$http下的一個函數複製代碼
嗯,完美,這樣就簡單的實現咱們的注入,但咱們仔細一下,若是這個時候咱們把這個依賴注入的順序變換一下是報錯的,由於他們是一一對應的,因此咱們還得來改造一下resolve這個方法,this
resolve: function(func, scope){
let arr = [];
// 這些正則是在angular的源碼裏找來的
// 首先把這個函數toString,而後FN_ARGS匹配出來函數的參數,這個參數就是咱們依賴的表
// 那麼這個時候咱們已經拿到依賴的表了,咱們按照這個表裏取出相對應的函數體給他就完了
let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
let fnText = func.toString().replace(STRIP_COMMENTS, '');
let argDecl = fnText.match(FN_ARGS);
let deps = argDecl[1].split(',');
for (let i = 0 ; i < deps.length ; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
return function(){
func.apply(scope||{},arr);
}
}複製代碼
固然使用的時候也得改一下spa
let MyController = function($scope,$http){
console.log(`MyController-result:${$http.get()}`)
}
MyController = inject.resolve(MyController)
MyController(); // MyController-result:我是依賴注入的$http下的一個函數複製代碼
看上去有點像模樣了,這時候我以爲應該有人會提出問題,嗯,對,就是還有問題,咱們知道上線前咱們通常會把項目靜態資源打包,function($scope,$http)會打成相似於function(a,b)這種,那麼這個時候還怎麼去打到對應的函數體呢 ? 咱們再來改寫一下resolve方法code
resolve: function(func, scope) {
let deps;
// 若是傳入的函數是一個數組,大概長這樣[a,b,function(a,b){}],那麼咱們刪掉function(){}這部分,只留下咱們的依賴部分,這樣就解決了打包壓縮時的問題
if (isArray(func)) {
let last = func.length - 1;
deps = func.slice(0, last);
func = func[last]
} else {
let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
let fnText = func.toString().replace(STRIP_COMMENTS, '');
let argDecl = fnText.match(FN_ARGS);
deps = argDecl[1].split(',');
}
let arr = [];
for (let i = 0; i < deps.length; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
return function() {
func.apply(scope || {}, arr);
}
}複製代碼
固然使用的時候仍是得改改對象
let MyController = ['$scope', '$http', function($scope, $http) {
console.log(`MyController-result:${$http.get()}`)
}];
MyController = inject.resolve(MyController)
MyController(); // MyController-result:我是依賴注入的$http下的一個函數複製代碼
這樣咱們一個簡易的dependencies inject就完成了,angular的實現思路也是如此ci