在用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 依赖注入--自己学着实现的更多相关文章

  1. AngularJS依赖注入

    <html> <head> <meta charset="utf-8"> <title>AngularJS 依赖注入</tit ...

  2. AngularJS 依赖注入

        依赖注入(Dependency Injection,简称DI)是一种软件设计模式,在这种模式下,一个或更多的依赖(或服务)被注入(或者通过引用传递)到一个独立的对象(或客户端)中,然后成为了该 ...

  3. 关于angularjs依赖注入的整理

    初学angularjs阶段,刚刚看到菜鸟教程的angularjs依赖注入.现在整理一下: 1.含义:一个或更多的依赖(可以理解为模块关系依赖)或服务(分为内建服务[例如$http,$tiomeout等 ...

  4. AngularJS开发指南10:AngularJS依赖注入的详解

    依赖注入是一种软件设计模式,用来处理代码的依赖关系. 一般来说有三种方法让函数获得它需要的依赖: 它的依赖是能被创建的,一般用new操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...

  5. (五)Angularjs - 依赖注入

    如何找到API? AngularJS提供了一些功能的封装,但是当你试图通过全局对象angular去 访问这些功能时,却发现与以往遇到的库大不相同. 比如,AngularJS暴露了一个全局对象:angu ...

  6. AngularJS - 依赖注入(Dependency Injection)

    点击查看AngularJS系列目录 转载请注明出处:http://www.cnblogs.com/leosx/ 依赖注入 依赖注入是软件设计模式中的一部分,用于处理组件是如何得到它说依赖的其它组件的. ...

  7. AngularJS——依赖注入

    依赖注入    依赖注入(DI)是一个经典的设计模式, 主要是用来处理组件如何获得依赖的问题.关于DI,推荐阅读Martin Flower的文章(http://martinfowler.com/art ...

  8. 个人对于angularjs依赖注入的理解

    依赖注入(Dependency Injection,DI),作者认为本文中所有名词性的"依赖" 都可以理解为 "需要使用的资源". 对象或者函数只有以下3种获取 ...

  9. angularjs 依赖注入原理与实现

    在用angular依赖注入时,感觉很好用,他的出现是 为了“削减计算机程序的耦合问题” ,我怀着敬畏与好奇的心情,轻轻的走进了angular源码,看看他到底是怎么实现的,我也想写个这么牛逼的功能.于是 ...

随机推荐

  1. 【AR实验室】ARToolKit之概述篇

    0x00 - 前言 我从去年就开始对AR(Augmented Reality)技术比较关注,但是去年AR行业一直处于偶尔发声的状态,丝毫没有其"异姓同名"的兄弟VR(Virtual ...

  2. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  3. C语言 · 4-3水仙花数

    问题描述 打印所有100至999之间的水仙花数.所谓水仙花数是指满足其各位数字立方和为该数字本身的整数,例如 153=1^3+5^3+3^3. 样例输入 一个满足题目要求的输入范例.例:无 样例输出 ...

  4. ajax

    常见的HTTP状态码状态码:200 请求成功.一般用于GET和POST方法 OK301 资源移动.所请求资源移动到新的URL,浏览器自动跳转到新的URL Moved Permanently304 未修 ...

  5. 使用CSS3实现一个3D相册

    CSS3系列我已经写过两篇文章,感兴趣的同学可以先看一下CSS3初体验之奇技淫巧,CSS3 3D立方体效果-transform也不过如此 第一篇主要列出了一些常用或经典的CSS3技巧和方法:第二篇是一 ...

  6. 【资源】.Net 入门@提高 - 逆天的高薪之路!

     入门看视频,提高看书籍,飘升做项目.老练研开源,高手读外文,大牛讲低调~    官方学习计划 http://www.cnblogs.com/dunitian/p/5667901.html ----- ...

  7. WinForm 天猫2013双11自动抢红包【源码下载】

    1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...

  8. Web APi之认证(Authentication)两种实现方式【二】(十三)

    前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再叙述废话. 序言 对于所谓的认证说到底 ...

  9. Android 工具-adb

    Android 工具-adb 版权声明:本文为博主原创文章,未经博主允许不得转载. Android 开发中, adb 是开发者经常使用的工具,是 Android 开发者必须掌握的. Android D ...

  10. 【HTML】Html页面跳转的5种方式

    目录结构: // contents structure [-] html实现 javascript方式实现 结合了倒数的javascript实现(IE) 解决Firefox不支持innerText的问 ...