kmdjs和循环依赖
循环依赖
循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚。所以没解决好循环依赖的模块化库、框架、编译器都不是一个好库、框架、编译器。
kmdjs的本质就是{},从{}扩展出的tree。从很早的版本就开始,是支持循环依赖的。比如下面的代码:
define('namespace1.A',['namespace2'], {
ctor: function () {
this.b = new B();
}
})
define('namespace2.B',['namespace1'] , {
ctor: function () {
},
xx: function () {
var a = new A();
}
})
会被kmdjs编译成:
var namespace1 = {};
var namespace2 = {};
namespace1.A = Class.extend({
ctor: function () {
this.b = new namespace2.B();
}
})
namespace2.B = Class.extend({
ctor: function () {
},
xx: function () {
var a = new namespace1.A();
}
})
要支持循环依赖其实有个要求,就是lazy using。不是lazy using的循环依赖是无解的循环依赖。
怎么理解上面这句话呢?看上面的代码,Class.extend执行完之后,各自依赖的东西是不会被调用的。
A代码里的new namespace2.B()要在new namespace1.A的时候才会被调用。
B代码里的new namespace1.A()要var a = new namespace1.A;a.xx()之后被调用后才会被执行。
所以在初始化阶段,这样的循环依赖是被允许的,因为都是lazy using。只要满足lazy using,执行顺序就不重要了,如果不是lazy using(如静态属性方法的设置),执行顺序就必须把依赖的项先执行。
如上面所说,不是所有的循环依赖都能够解决的,比如看C#里面的无解的循环依赖的例子:
namespace Project1
{
public class A
{
public static B b = new B();
}
}
namespace Project1
{
public class B
{
public static A a = new A();
}
}
上面的代码编译时候就会报错。怎么改成有解,那么就要lazy using:
namespace Project1
{
public class A
{
public static B b = new B();
}
}
namespace Project1
{
public class B
{
public int testMethod()
{
A a = new A();
return 1;
}
}
}
这样的依赖编译器是可以解决的。
kmdjs 0.1.4
kmd的意思是 kernel module definition。该版本和以前的主要变化如下:
- kmdjs文件大小从以前的一万多行代码变成了一百多行代码
- 从以前的namespace+class组织项目变成namespace+module组织项目
kmdjs API
kmdjs.config
用于配置 namespace + module和文件路径的mapping
kmdjs.config({
'util.bom':'js/util/bom.js',
'app.Ball':'js/ball.js',
'util.dom':'js/util/dom.js',
'util.dom.test':'js/util/test.js',
'main': 'js/main.js'
});
kmdjs.main
程序的入口代码。
kmdjs.define
定义模块
kmdjs.define('main',['util.bom','app.Ball','util.dom.test'], function(bom,Ball,test) {
var ball = new Ball(0, 0, 28, 1, -2, 'kmdjs');
alert(test.m(3, 3));
var vp = bom.getViewport();
setInterval(function () {
ball.tick();
(ball.x + ball.r * 2 > vp[2] || ball.x < 0) && (ball.vx *= -1);
(ball.y + ball.r * 2 > vp[3] || ball.y < 0) && (ball.vy *= -1);
}, 15);
});
如果只传两个参数,代表不依赖任何模块。这里和AMD一样,在factory的回调里把依赖注入到里面。
但是也直接在代码里把namespace写进去访问,如下所示:
kmdjs.define('main',['util.bom','app.Ball'], function() {
var ball = new app.Ball(0, 0, 28, 1, -2, 'kmdjs');
var vp = util.bom.getViewport();
setInterval(function () {
ball.tick();
(ball.x + ball.r * 2 > vp[2] || ball.x < 0) && (ball.vx *= -1);
(ball.y + ball.r * 2 > vp[3] || ball.y < 0) && (ball.vy *= -1);
}, 15);
});
而有的时候必须使用上面这种方式用来解决循环依赖导致执行顺序问题带来的注入undefined:如:
kmdjs.define("util.dom",['util.bom'] ,function(bom){
var Dom={};
Dom.add = function(a,b){
//循环依赖导致的bom undefined,所以这里写上namespace
return util.bom.sub(a,b);
}
return Dom;
});
和
kmdjs.define("util.bom",["util.dom"], function(dom){
var Bom={};
Bom.getViewport=function() {
alert(dom.add(1,4));
};
Bom.sub = function(a,b){
return a-b;
};
return Bom;
});
bundler
可以通过main传入回调函数,在回调函数中拿到编辑打包好的字符串。
kmdjs.main(function(bundler){
alert(bundler)
});
如上面的例子打包出来的代码:
var util={};
var app={};
util.dom={};
var main={};
util.dom = (function (bom){
var Dom={};
Dom.add = function(a,b){
return util.bom.sub(a,b);
}
return Dom;
})(util.bom);
app.Ball = (function (){
var Ball = function (x, y, r, vx, vy, text) {
this.x = x;
this.y = y;
this.r = r;
this.d = 2 * r;
this.vx = vx;
this.vy = vy;
this.element = document.createElement("div");
this.element.innerHTML = text;
this.element.style.cssText = "text-align:center;position:absolute; -moz-border-radius:" + this.d + "px; border-radius: " + this.d + "px; width: " + this.d + "px; height: " + this.d + "px;background-color:green;line-height:" + this.d + "px;color:white;";
document.body.appendChild(this.element);
};
Ball.prototype.tick= function () {
this.x += this.vx;
this.y += this.vy;
this.element.style.left = this.x + "px";
this.element.style.top = this.y + "px";
};
return Ball;
})();
util.dom.test = (function (){
var Element={};
Element.m = function(a,b){
return a*b;
}
return Element;
})();
util.bom = (function (dom){
var Bom={};
Bom.getViewport=function() {
alert(dom.add(1,4));
var d = document.documentElement, b = document.body, w = window, div = document.createElement("div");
div.innerHTML = " <div></div>";
var lt = !(div.firstChild.nodeType === 3) ?
{ left: b.scrollLeft || d.scrollLeft, top: b.scrollTop || d.scrollTop } :
{ left: w.pageXOffset, top: w.pageYOffset };
var wh = w.innerWidth ?
{ width: w.innerWidth, height: w.innerHeight } :
(d && d.clientWidth && d.clientWidth != 0 ?
{ width: d.clientWidth, height: d.clientHeight } :
{ width: b.clientWidth, height: b.clientHeight });
return [lt.left, lt.top, wh.width, wh.height]
};
Bom.sub = function(a,b){
return a-b;
};
return Bom;
})(util.dom);
main = (function (bom,Ball,test) {
var ball = new Ball(0, 0, 28, 1, -2, 'kmdjs');
alert(test.m(3, 3));
var vp = bom.getViewport();
setInterval(function () {
ball.tick();
(ball.x + ball.r * 2 > vp[2] || ball.x < 0) && (ball.vx *= -1);
(ball.y + ball.r * 2 > vp[3] || ball.y < 0) && (ball.vy *= -1);
}, 15);
})(util.bom,app.Ball,util.dom.test);
Github
https://github.com/kmdjs/kmdjs
kmdjs和循环依赖的更多相关文章
- js和循环依赖
kmdjs和循环依赖 循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚.所以没解决好循环依赖的模块化库.框架.编译器 ...
- spring3 循环依赖
循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...
- 在.NET Core中遭遇循环依赖问题"A circular dependency was detected"
今天在将一个项目迁移至ASP.NET Core的过程中遭遇一个循环依赖问题,错误信息如下: A circular dependency was detected for the service of ...
- seaJS循环依赖的解决原理
seajs模块的六个状态. var STATUS = { 'FETCHING': 1, // The module file is fetching now. 模块正在下载中 'FETCHED': ...
- RequireJS 循环依赖报 模块undefined 处理方案
RequireJS 循环依赖 开始学习使用RequireJS之后做了几个小例子,之后想着把手头的项目也用RequireJS写一遍试试.感觉胜利就在前方了,忽然发现始终卡在一个问题上: 很常见的一个问题 ...
- 剑指架构师系列-Struts2构造函数的循环依赖注入
Struts2可以完成构造函数的循环依赖注入,来看看Struts2的大师们是怎么做到的吧! 首先定义IBlood与BloodImpl类: public interface IBlood { } pub ...
- Spring的循环依赖问题
spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循环引用类: 在Spring中将循环依赖的处理分成了3种情况: 构造器循环依赖 ...
- Spring对加载的bean之间循环依赖的处理
根据下面文档的叙述,简言之: 对于相互之间通过构造函数注入相互循环依赖的情况,Spring会抛出BeanCurrentlyInCreationException错误. 如果AB两个beans是通过属性 ...
- DI 之 3.2 循环依赖 (伍)
3.2.1 什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA, ...
随机推荐
- 高仿it之家新闻客户端源码
仿it之家新闻客户端界面,数据为本地假数据.仅实现了新闻模块的功能. 源码下载:http://code.662p.com/list/11_1.html 详细说明:http://android.662p ...
- Linux基础介绍【第七篇】
linux用户分类 超级用户:UID=0,root 普通用户:UID 500起,由超级用户或具有超级用户权限的用户创建的用户. 虚拟用户:UID 1-499,为了满足文件或服务启动的需要而存在,一般都 ...
- git常用命令(持续更新中)
git常用命令(持续更新中) 本地仓库操作git int 初始化本地仓库git add . ...
- emmet,jade,haml, slim,less,sass,coffeescript等的实战优缺点
摘要: 文章背景,来自于群内周五晚上的一次头脑风暴式的思维碰撞交流活动. 随着前端技术的蓬勃发展, 各种新技术随着生产力的需要不断的涌入我们的视野, 那今天探讨的话题是这些新时代的前端兵器谱: 一. ...
- kvm上的Linux虚拟机使用virtio磁盘
kvm上的Linux虚拟机使用virtio磁盘 系统:centos6.6 64位 网上的文章比较少,怎麽将Linux虚拟机的磁盘改为使用virtio磁盘 因为centos6或以上系统已经包含了vir ...
- ASP.NET Core Loves JavaScript
前言 在 ASP.NET 团队的 Github 的主页上,有这样一个开源项目叫:"JavaScriptsServices",那么 什么是 JavaScriptsServices 呢 ...
- 腾讯云 安装mono
一.yum -y update 运行出现以下错误: http://centos.tencentyun.com/contrib/x86_64/repodata/filelists.xml.gz: [Er ...
- Angular2学习笔记——路由器模型(Router)
Angular2以组件化的视角来看待web应用,使用Angular2开发的web应用,就是一棵组件树.组件大致分为两类:一类是如list.table这种通放之四海而皆准的通用组件,一类是专为业务开发的 ...
- Vim新手入门资料和一些Vim实用小技巧
一些网络上质量较高的Vim资料 从我07年接触Vim以来,已经过去了8个年头,期间看过很多的Vim文章,我自己觉得非常不错,而且创作时间也比较近的文章有如下这些. Vim入门 目前为阿里巴巴高级技术专 ...
- PHP安装mysql.so扩展
在PHP中mysql_connect模块已经逐渐被弃用,我在搭建环境时也没有再安装mysql扩展,但是今天在维护一个老项目时,出现报错 Fatal error: Uncaught Error: Cal ...