总体思路就是用闭包实现的singleton(单例模式)以及DI(依赖注入),所有的service都是驻留在内存中,Provider下声场的s1,s2,s3是唯一的且全局可访问的(下面例子中其实就是injector)controller在实例化的时候可以直接根据参数获取到相应的service实例从而调用,这样就实现了在controller中的DI,注入自定义的provider或者service(服务),而无需自己手动import进来,当然,真正angularJS中要比这个要复杂很多,因为还包含了scope(作用域)的管理,以及循环依赖一些的异常处理,包括还有一个全局的$injector provider可以显式的DI 类似 ctr1.$injector = ['service1', 'service2',....];
服务
var Provider = (function(){
var injector = {};
return {
service: function(serviceName, fn){
if(!injector[serviceName]){
injector[serviceName] = fn();
}else{
console.log('already has a instance');
}
},
inject: function(serviceName){
if(!injector[serviceName]){
console.log('no instance for'+ serviceName);
}
return injector[serviceName];
}
}
})();
控制器
function Controller(ctrlName, fn){
var injector = Provider;
return function(){
//是否有显式的指定相应的DI 没有则尝试取形参
var serviceList = fn.$injector ? fn.$injector : getArgumentsList(fn);
var serviceImpList = [];
serviceList.forEach(function(serviceName){
serviceImpList.push(injector.inject(serviceName));
});
fn.apply(null, serviceImpList)
}
};
function getArgumentsList(func){
var funcString = func.toString();
var regExp =/function\s*\w*\(([\s\S]*?)\)/;
if(regExp.test(funcString)){
var argList = RegExp.$1.split(',');
return argList.map(function(arg){
return arg.replace(/\s/g,'');
});
}else{
return []
}
}
服务初始化
Provider.service('s1', function(){
return {name: 's1'};
})
Provider.service('s2', function(){
return {name: 's2'};
})
Provider.service('s3', function(){
return {
name: 's3',
sayHello: function(){
console.log('hello i m s3');
}
};
})
Provider.service('s4', function(){
return {
name: 's4',
getName: function(t){
console.log('hello i m '+ t);
}
};
})
var fn1 = function(s1,s2,s3){
// console.log(this);
console.log(s1);
console.log(s2.name);
console.log('change s2 name to patrick');
s2.name = 'patrick';
console.log(s3.sayHello())
};
var fn2 = function(s2, s4){
console.log(s2.name);
console.log(s4.getName('wxy'))
}
var fn3 = function(s2, s4){
console.log(s2.name);
console.log(s4.getName('wxy2'))
}
//DI
fn3.$injector = ['s2', 's4'];
var ctr3 = new Controller('c3Name', fn3);
var ctr1 = new Controller('c1Name', fn1);
var ctr2 = new Controller('c2Name', fn2);
ctr1();
ctr2();
ctr3();