博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
kmdjs和循环依赖
阅读量:6094 次
发布时间:2019-06-20

本文共 5616 字,大约阅读时间需要 18 分钟。

循环依赖

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

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 = "  
"; 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

转载地址:http://giwza.baihongyu.com/

你可能感兴趣的文章
《剑指offer》-统计整数二进制表示中1的个数
查看>>
stringBuffer
查看>>
50.3. resin.conf
查看>>
nodejs express
查看>>
企业级负载平衡简介(转)
查看>>
ICCV2017 论文浏览记录
查看>>
科技巨头的交通争夺战
查看>>
【高德地图API】从零开始学高德JS API(七)——定位方式大揭秘
查看>>
Nmon 性能:分析 AIX 和 Linux 性能的免费工具
查看>>
obs nginx-rtmp-module搭建流媒体服务器实现直播 ding
查看>>
当中兴安卓手机遇上农行音频通用K宝 -- 卡在“正在通讯”,一直加载中
查看>>
5G第二阶段测试年底收官 第三阶段测试明年一季度启动
查看>>
PowerDesigner概念模型与物理模型相互转换及导出数据字典
查看>>
温故知新,基础复习(一个有序从大到小不重复的数列,任意给出一个sum值,求出数列中所有满足和为sum的数对)...
查看>>
Office Web Apps安装部署
查看>>
C++之static_cast, dynamic_cast, const_cast
查看>>
Java初级笔记-第二章
查看>>
android EditText长按屏蔽ActionMode context菜单但保留选择工具功能
查看>>
Git 遇到了 early EOF index-pack failed 问题
查看>>
统计学习方法(二)感知器C语音实现
查看>>