angularjs 依赖注入--自己学着实现
在用angular依赖注入时,感觉很好用,他的出现是 为了“削减计算机程序的耦合问题” ,我怀着敬畏与好奇的心情,轻轻的走进了angular源码,看看他到底是怎么实现的,我也想写个这么牛逼的功能。于是就模仿着写了一个,如果有什么不对,请大家批评指正。
其实刚开始的时候我也不知道怎么下手,源码中有些确实晦涩难懂,到现在我也没有看明白,于是我就静下心想一想,他是怎么用的,如下所示:
angular.module(/*省略*/)
.factory("xxxService", ['xx',function (xx) {
return {
//省略
}
}])
.controller('iiController',['xxxService',function(xxxService){
//省略
}]);
/*...方法省略..*/
看看上面严格模式下的使用方式,先不去看源码,如何实现service重用,controller不重用呢? 我就按照自己的想法创建一个cache用于保存service,controller 只运行一次,不保存到cache中。
有了点思路,就把该有的东西先写了,
(function (global) {
function CreateInjector(cache){
this.cache=cache;//用于保存service的cache
}
function Angular(){}
Angular.module=function(){
var moduleObj={};
return {
injector:new CreateInjector(moduleObj),
factory:function(name,fn){
},
controller:function(name,fn){
}
}
};
global.angular = Angular;
})(window);
上面两个构造函数,一个是创建构造器,一个是angular 的静态module(不用创建直接用 "构造函数名.方法名",这里就是想模仿angular.module())方法,这里angular module 的方法我简写了,他也有依赖注入,但是我能力有限,先研究了controller和service的注入。上面的方法名字都是我copy于源码中的,这里我就不解释他们的具体意义了。
由于我们研究的是依赖注入,真正的核心代码如下:
var ARROW_ARG = /^([^\(]+?)=>/;
var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
function isArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]';
}
function stringifyFn(fn) {
return fn.toString();
} function extractArgs(fn) {
var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''),
args= fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
return args[1].split(',');
}
function CreateInjector(cache){
this.cache=cache;
}
CreateInjector.prototype={
constructor:CreateInjector,
invoke:function(fn,self){
var argsName= extractArgs(fn),argsFn=[];
argsName.forEach(function(arg){
argsFn.push(this.cache[arg]);
},this);
if(isArray(fn)){
return fn[fn.length-1].apply(self,argsFn);
}else{
return fn.apply(self,argsFn);
}
}
};
其中上面的正则表达式是复制于源码中的,代码原理是:
(1)把传来的function toString(),然后用正则match出所传参数名,用split把参数分割成参数数组;
(2)循环参数数组,在cache中找到此参数名下的函数,push到一个函数数组中;
(3)利用apply,把函数数组当成参数,去执行函数;
对于所传的fn, 判断是数组格式,还是普通的,如果是数组就apply最后的一个值,也就是函数,否则就是fn自己。
上面的我没有做错误处理,比如注入的找不到等等一些问题,有兴趣自己加上吧。
最后所有代码如下,大家可以复制运行:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>angular injector Demo</title>
</head>
<body>
<script>
(function (global) {
var ARROW_ARG = /^([^\(]+?)=>/;
var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
function isArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]';
}
function stringifyFn(fn) {
return fn.toString();
} function extractArgs(fn) {
var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''),
args= fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
return args[1].split(',');
}
function CreateInjector(cache){
this.cache=cache;
}
CreateInjector.prototype={
constructor:CreateInjector,
invoke:function(fn,self){
var argsName= extractArgs(fn),argsFn=[];
argsName.forEach(function(arg){
argsFn.push(this.cache[arg]);
},this);
if(isArray(fn)){
return fn[fn.length-1].apply(self,argsFn);
}else{
return fn.apply(self,argsFn);
}
}
};
function Angular(){}
Angular.module=function(){
var moduleObj={};
return {
injector:new CreateInjector(moduleObj),
factory:function(name,fn){
moduleObj[name]=this.injector.invoke(fn);
return this;
},
controller:function(name,fn){
this.injector.invoke(fn);
return this;
}
}
};
global.angular = Angular;
})(window); angular.module()
.factory('cacheService',[function(){
return {};
}])
.factory("userInfoService", ['cacheService',function (cacheService) {
return {
getUserInfo:function(){
return cacheService.userInfo;
},
setUserInfo:function(value){
cacheService.userInfo=value;
}
}
}])
.controller('userController',['userInfoService',function(userInfoService){
userInfoService.setUserInfo({id:'qqqq11234',name:'zhangLearing'});
console.log(userInfoService.getUserInfo());
}]);
</script>
</body>
</html>
谢谢大家!
angularjs 依赖注入--自己学着实现的更多相关文章
- AngularJS依赖注入
<html> <head> <meta charset="utf-8"> <title>AngularJS 依赖注入</tit ...
- AngularJS 依赖注入
依赖注入(Dependency Injection,简称DI)是一种软件设计模式,在这种模式下,一个或更多的依赖(或服务)被注入(或者通过引用传递)到一个独立的对象(或客户端)中,然后成为了该 ...
- 关于angularjs依赖注入的整理
初学angularjs阶段,刚刚看到菜鸟教程的angularjs依赖注入.现在整理一下: 1.含义:一个或更多的依赖(可以理解为模块关系依赖)或服务(分为内建服务[例如$http,$tiomeout等 ...
- AngularJS开发指南10:AngularJS依赖注入的详解
依赖注入是一种软件设计模式,用来处理代码的依赖关系. 一般来说有三种方法让函数获得它需要的依赖: 它的依赖是能被创建的,一般用new操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...
- (五)Angularjs - 依赖注入
如何找到API? AngularJS提供了一些功能的封装,但是当你试图通过全局对象angular去 访问这些功能时,却发现与以往遇到的库大不相同. 比如,AngularJS暴露了一个全局对象:angu ...
- AngularJS - 依赖注入(Dependency Injection)
点击查看AngularJS系列目录 转载请注明出处:http://www.cnblogs.com/leosx/ 依赖注入 依赖注入是软件设计模式中的一部分,用于处理组件是如何得到它说依赖的其它组件的. ...
- AngularJS——依赖注入
依赖注入 依赖注入(DI)是一个经典的设计模式, 主要是用来处理组件如何获得依赖的问题.关于DI,推荐阅读Martin Flower的文章(http://martinfowler.com/art ...
- 个人对于angularjs依赖注入的理解
依赖注入(Dependency Injection,DI),作者认为本文中所有名词性的"依赖" 都可以理解为 "需要使用的资源". 对象或者函数只有以下3种获取 ...
- angularjs 依赖注入原理与实现
在用angular依赖注入时,感觉很好用,他的出现是 为了“削减计算机程序的耦合问题” ,我怀着敬畏与好奇的心情,轻轻的走进了angular源码,看看他到底是怎么实现的,我也想写个这么牛逼的功能.于是 ...
随机推荐
- XSS
XSS的含义 XSS(Cross Site Scripting)即跨站脚本.跨站的主要内容是在脚本上. 跨站脚本 跨站脚本的跨,体现了浏览器的特性,可以跨域.所以也就给远程代码或者第三方域上的代码提供 ...
- 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域
一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...
- Docker 第一篇--初识docker
已经多年不写博客, 看完<晓松奇谈>最后一期猛然觉醒, 决定仔细梳理下自己这几年的知识脉络. 既然决定写, 那么首先就从最近2年热门的开源项目Docker开始.Docker 这两年在国内很 ...
- jQuery学习之路(2)-DOM操作
▓▓▓▓▓▓ 大致介绍 jQuery作为JavaScript库,继承并发扬了JavaScript对DOM对象操作的特性,使开发人员能方便的操作DOM对象. ▓▓▓▓▓▓ jQuery中的DOM操作 看 ...
- Linux学习之探索文件系统
Linux,一起学习进步- ls With it, we can see directory contents and determine a variety of important file ...
- 如何利用ansible callback插件对执行结果进行解析
最近在写一个批量巡检工具,利用ansible将脚本推到各个机器上执行,然后将执行的结果以json格式返回来. 如下所示: # ansible node2 -m script -a /root/pyth ...
- [转载]Cookie/Session的机制与安全
Cookie和Session是为了在无状态的HTTP协议之上维护会话状态,使得服务器可以知道当前是和哪个客户在打交道.本文来详细讨论Cookie和Session的实现机制,以及其中涉及的安全问题. 因 ...
- 值得注意的ibatis动态sql语法格式
一.Ibatis常用动态sql语法,简单粗暴用一例子 <select id="iBatisSelectList" parameterClass="java.util ...
- 解决IE8下不兼容rgba()的解决办法
rgba()是css3的新属性,所以IE8及以下浏览器不兼容,这怎么办呢?终于我找到了解决办法. 解决办法 我们先来解释以下rgba rgba: rgba的含义,r代表red,g代表green,b代表 ...
- IT雇员及外包商选择:人品第一
最近,苹果iOS操作系统和智能手机爆出了一个奇葩故障,在播放特定一段五秒钟的视频时能导致手机死机.唯一的解决办法是按住电源键和Home按键进行手机的重启. 第十八届中国国际高新技术成果交易会在深圳举办 ...