循环依赖

循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚。所以没解决好循环依赖的模块化库、框架、编译器都不是一个好库、框架、编译器。

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。该版本和以前的主要变化如下:

  1. kmdjs文件大小从以前的一万多行代码变成了一百多行代码
  2. 从以前的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和循环依赖的更多相关文章

  1. js和循环依赖

    kmdjs和循环依赖 循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚.所以没解决好循环依赖的模块化库.框架.编译器 ...

  2. spring3 循环依赖

    循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...

  3. 在.NET Core中遭遇循环依赖问题"A circular dependency was detected"

    今天在将一个项目迁移至ASP.NET Core的过程中遭遇一个循环依赖问题,错误信息如下: A circular dependency was detected for the service of ...

  4. seaJS循环依赖的解决原理

    seajs模块的六个状态. var STATUS = {  'FETCHING': 1, // The module file is fetching now. 模块正在下载中  'FETCHED': ...

  5. RequireJS 循环依赖报 模块undefined 处理方案

    RequireJS 循环依赖 开始学习使用RequireJS之后做了几个小例子,之后想着把手头的项目也用RequireJS写一遍试试.感觉胜利就在前方了,忽然发现始终卡在一个问题上: 很常见的一个问题 ...

  6. 剑指架构师系列-Struts2构造函数的循环依赖注入

    Struts2可以完成构造函数的循环依赖注入,来看看Struts2的大师们是怎么做到的吧! 首先定义IBlood与BloodImpl类: public interface IBlood { } pub ...

  7. Spring的循环依赖问题

    spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循环引用类: 在Spring中将循环依赖的处理分成了3种情况: 构造器循环依赖 ...

  8. Spring对加载的bean之间循环依赖的处理

    根据下面文档的叙述,简言之: 对于相互之间通过构造函数注入相互循环依赖的情况,Spring会抛出BeanCurrentlyInCreationException错误. 如果AB两个beans是通过属性 ...

  9. DI 之 3.2 循环依赖 (伍)

    3.2.1  什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA, ...

随机推荐

  1. SpringMvc中的数据校验

    SpringMvc中的数据校验 Hibernate校验框架中提供了很多注解的校验,如下: 注解 运行时检查 @AssertFalse 被注解的元素必须为false @AssertTrue 被注解的元素 ...

  2. mono for android 用ISharedPreferences 进行状态保持 会话保持 应用程序首选项保存

    由于项目需要 要保持用户登录状态 要进行状态保持 用途就好像asp.net的session一样 登录的时候进行保存 ISharedPreferences shared = GetSharedPrefe ...

  3. 从零开始,DIY一个jQuery(1)

    从本篇开始会陪大家一起从零开始走一遍 jQuery 的奇妙旅途,在整个系列的实践中,我们会把 jQuery 的主要功能模块都了解和实现一遍. 这会是一段很长的历程,但也会很有意思 —— 作为前端领域的 ...

  4. WPF - 属性系统 (3 of 4)

    依赖项属性元数据 在前面的章节中,我们已经介绍了WPF依赖项属性元数据中的两个组成:CoerceValueCallback回调以及PropertyChangedCallback.而在本节中,我们将对其 ...

  5. 微信硬件H5面板开发(一) ---- 调用openApi

    微信硬件平台是微信推出连接物与人,物与物的IOT解决方案.也就是说可以通过微信控制各种智能设备.比如一些蓝牙设备.空调.电视等等. 我本身不懂硬件(虽然是电子信息专业),硬件是北航的两个研究生在弄,小 ...

  6. 基于Quick-cocos2d-x的资源更新方案 二

    写在前面 又是12点半了,对于一个程序员来说,这是一个黄金时间,精力旺盛,我想,是最适合整理和分享一些思路的时候了. 自从上次写了 基于Quick-cocos2d-x的资源更新方案 同样可见quick ...

  7. JavaScript随笔3

    1.获取非行间css if(oDiv.currentStyle){ alert(oDiv.currentStyle.width); }else{ alert(oDiv.getComputedStyle ...

  8. sublime text添加snippet

    下面的${1:this}格式的会在tab键下一次切换选中 <snippet> <content><![CDATA[Hello, ${1:this} is a ${2:sn ...

  9. 解析大型.NET ERP系统 分布式应用模式设计与实现

    C/S架构的应用程序,将一些复杂的计算逻辑由客户端转移到服务器端可以改善性能,同时也为了其它方面的控制..NET Remoting在局域网内调用的性能相当不错.ERP系统中基于.NET Remotin ...

  10. 计算机网络学习笔记--网络层之IP地址与子网

    IPv4地址: 我们知道在网络层(TCP/IP体系结构的网际互联层),最重要的一个协议就是IP协议,现在正处于IPv4和IPv6的过渡时期,但目前来说,IPv4仍为主流,所以主要讲Ipv4. IP地址 ...