javascript的DI
2024-09-01 14:15:06
学习AngularJS的原因之一就是觉得他的DI很牛叉,为了更好的学习,在研究源码之前,想自己按照自己的思路先实现个DI,希望这个思路能够对
学习源码有帮助。
(function(){
var config;
var di={};
//用来缓存已经生成的对象
var beans=new Array();
di.config=function(conf){
this.config=conf;
return di;
}; /*获取一个方法的参数列表,要求所有注入的参数都已$开头
第二个正则表达是后面的 g 很重要,它表示搜索到第一个之后接着往后搜
没有这个g ,就只能match第一个参数。
这里的参数列表指的就是代码中写的参数列表,不是带入参数后的参数类表
比如有一个方法:
function Fn(a,b,c,c1){}
参数列表就是一个有四个字符串组成的数组:["a","b","c","c1"]
因为需要有参数的名字去匹配参数的类型
*/
var getArguments=function(fun){
return fun.toString().match(/\(.*\)/)[0].match(/\$\w+/g);
};
//核心方法
di.getBean=function(beanName){
//查看缓存,有的话直接返回
if(beans[beanName]!=undefined)
return beans[beanName];
var fn=this.config[beanName];
if(fn==undefined) return;
var args=getArguments(fn);
var argss=new Array();
var objstr="";
var index=0;
var obj;
for(var i in args){
argss[i]=(di.getBean(args[i]));
objstr+="argss["+index+"],";
index++;
}
objstr=objstr.substring(0, objstr.length-1);
objstr="obj=new (fn)("+objstr+"); ";
/*整个DI能够实现就靠这个eval方法了,
它接受一个String参数,并把String里面的内容按照Javasript的标准编译并执行
最牛叉的是eval里面的变量也遵循Javascript的函数作用域:也就是变量可以定义在eval外面
*/
/*
当然这里也可以用apply,或者call,不过总有这样那样的问题,可能是自己对这两个方法不够了解吧
先用eval实现了,以后再研究apply 和call
*/
eval(objstr);
beans[beanName]=obj;
return obj;
};
window.di=di;
})(window);
下面是个例子,
function Person(){
this.name="Mike";
this.address="China"; this.getName=function(){
return this.name;
};
this.getAddress=function(){
return this .address;
};
}
function Service($person){
this.work=function(){
return $person.getName()+" is living in "+$person.getAddress();
};
} function Adaptor($person,$service){
this.alertt=function(){
var k=$service.work();
alert(k);
};
}
有Person,Service,Adaptor三个类,Service类依赖Person来组装语句,Adaptor类依赖Service类来显示,只要有下面的代码就能运行了
var conf={
"$person":Person,
"$adaptor":Adaptor,
"$service":Service
};
di.config(conf).getBean("$adaptor").alertt();
目前这种DI有个缺陷就是没法再组装时决定类的状态。比如一开始new一个Person时想通过构造方法给name赋值,以上的方式是不能直接做不到的。
只能通过一个间接地方式,如下:
function Person(){
this.name="Mike";
this.getName=function(){
return this.name;
};
this.setName=function($name){
this.name=$name.Name;
};
}
function Name(){
this.NAME="Tom";
}
//然后在Service中使用Person前重新给name赋值
function Service($person,$name){
this.work=function(){
$person.setName($name.NAME);
return $person.getName()+" is living in China"; //这里就成了 Tom is living in China
};
}
最新文章
- 在linux 服务器上用.htaccess文件实现二级域名访问子目录
- java中文乱码解决之道(二)-----字符编码详解:基础知识 + ASCII + GB**
- linux sysnc
- 我的github代码库
- centos---无线上网的电脑所安装的虚拟机网络设置
- 转!!URL 传+号到后台变空格问题解决方案
- uva 562
- 表单设置line-height,在ff中的不垂直居中问题???
- C++学习50 对字符串流的读写
- stl_alloc.h
- Performing Post-Build Event之类的编译错误
- MTK Android Driver:GPIO
- 【操作教程】利用YCSB测试巨杉数据库性能
- 【RabbitMQ+Python入门经典】兔子和兔子窝 笔记
- Spring ConditionalOnProperty
- hdu3374 最大最小表示法 +kmp
- Vivado HLS初识---阅读《vivado design suite tutorial-high-level synthesis》(5)
- MeasureOverride和ArrangeOverride 练手项目
- RestClient POST
- 本地schemeApp扩展
热门文章
- spring装配机制
- RabbitMQ事务确认机制(生产者)
- Mybatis异常_01_Invalid bound statement (not found)
- FileInputStream 把文件作为字节流进行读操作
- Agc017_E Jigsaw
- Gym 101142C :CodeCoder vs TopForces(强连通算法)
- 2017-2018-1 20179203 《Linux内核原理与分析》第九周作业
- bzoj 1312: Hard Life 01分数规划+网络流
- 【LeetCode】012. Integer to Roman
- 浏览器全屏的JS代码实现