Dojo面向对象机制深入剖析

dojo常用方法总结 dojo常用方法总结,主要是元素的获取,事件的监听,数组的遍历等 立即下载

 

Dojo是一个基于javascript语言的web控件库,要了解dojo的面向对象机制,我们可以首先来回顾一下javascript本身的基本面向对象机制:

 

首先,javascript主要通过函数来模拟面向对象机制,如:

function func1(){};

func1();  //函数调用

new func1();  //实例化的对象

上述两种方式其函数内部的this对象也是不一样的。

 

再者,关于javascript的最基本的继承方式主要有两种,(当然还有更复杂的,这里只列出最基本的两种方式)

1. 对象冒充方式:

function ClassA(sColor) {
    this.color = sColor;
    this.xxx = xxx;
   ......
}

function ClassB(sColor, name) {
    this.newMethod = ClassA;
    this.newMethod(sColor);
    delete this.newMethod;
   ......
}  

或者:(这里ClassA同上)

function ClassB(sColor, sName)  { 
    ClassA.call(this, sColor);  //或者apply
 
    this.name =  sName; 
    this.sayName = function() { 
        alert(this.name); 
    }; 
} 

 

 

 

2. 原型链式继承:

//基类

function ClassA() { } 
ClassA.... = .....; 
//子类 
function ClassB() { } 
//通过修改prototype来达到继承目的
ClassB.prototype = new ClassA(); 

//定义新属性与方法 
ClassB.... = .....;

//保证constructor的一致性(修改prototype后其constructor变为ClassA,应该是ClassB)

ClassB.prototype.constructor = ClassB;

 

 

上述两种方法各有优缺点:对象冒充方式效率低,而且必须使用构造函数方式但是能支持多继承,而prototype方式很灵活但不支持多继承。于是有了如下混合方式:

function ClassA(sColor) { } 
ClassA.... = ..... //设置属性

function ClassB() { 
    ClassA.call(this, sColor);   //对象冒充方式  继承属性 
    this.name = sName; 
} 
ClassB.prototype = new ClassA();  //原型链方式 继承方法 
ClassB.prototype.sayName = function() { 
    alert(this.name); 
} 

 

 

下面我们来看看dojo是如何实现继承机制的:

下面是dojo中声明类和使用类的一个简单示例,可以看出,其核心在一个dojo.declare函数上:

 

我们来看看dojo.declare函数:

1> 先看第一个参数:className参数,可以见如下相关代码:

......

// add name if specified
if(className){
    proto.declaredClass = className;
    d.setObject(className, ctor);
}

......

 

其中ctor是在该方法内构造的一个函数,其实是该声明类的定义,其本身是一个函数对象,里面有很多成员:包括属性定义,函数定义,关于这个的详细介绍这个后面会涉及到。这里主要通过dojo.setObject将该构造的函数对象赋给名为className的变量,如dijit.WidgetSet.

所以这里相当于这样写:

ctor = function(){....};

Dijit.WidgetSet = ctor;

 

另外强调一下,这里的proto就是ctor的prototype.

 

 

2> 我们再来看看第三个参数:props,可以见如下代码:(具体可见加粗的字体说明)

............

proto = {};


//复制一份类的定义对象的内容,见上面Dijit.Calendar的templateString, value, buildRendering等等属性和方法.
safeMixin(proto, props);



// 开始构造ctor,即构造类的定义,可以看到里面还有很多dojo自己添加的属性
t = !chains || !chains.hasOwnProperty(cname);

//以下三个对象singleConstructor/simpleConstructor/chainedConstructor   都是 是一个函数对象,其返回值也是一个函数对像,这些返回的函数对象内部,都会包含一些默认操作,包括初始化,调用ctor及其基类的ctor等等,具体细节可以参见上述三个函数的定义,可以看出模拟dojo的类的函数在初始化时都做了些什么,很值得研究,为了是篇幅不要太长,这里暂时不做过于细致的深入。
bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
    (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));

// add meta information to the constructor

//这里的ctor属性很关键,在上面提到的 singleConstructor/simpleConstructor/chainedConstructor函数里面会调用到,这也是为什么dojo.declare的“类”在初始化时(new操作)会自动调用constructor方法的原因!!!
ctor._meta  = {bases: bases, hidden: props, chains: chains,
    parents: parents, ctor: props.constructor };
ctor.superclass = superclass && superclass.prototype;
ctor.extend = extend;

 

//这里是比较关键的操作了,将定义的属性全部作为prototype的属性,注意我们这里先不谈继承,而且这里不是在继承,请和前面的javascript继承区分开

ctor.prototype = proto;

//由于prototype被修改,所以需要重新赋值以保持prototype的constructor一致性
proto.constructor = ctor;

// 添加dojo里面比较常用的方法,注意:这些方法被直接加到了prototype中!
proto.getInherited = getInherited;
proto.inherited = inherited;
proto.isInstanceOf = isInstanceOf;

............


//最后将构造好的类对象ctor(本质上是一个函数对象)赋值给我们声明的类名
dojo.setObject(className, ctor)

.............

 

所以这里其实可以知道,在dojo中declare的类,其本质是函数对象,其实他就是如下代码:

ctor = function(){};

ctor.prototype = props 属性定义.....

类名变量{eval(className)} = ctor;

 

 

3> 下面我们来看一看第二个参数,关系着dojo的继承机制:(具体可见加粗的字体说明)

..................

if(opts.call(superclass) == "[object Array]"){
    //多个基类时,整理基类数组
    bases = c3mro(superclass);
    t = bases[0];
    mixins = bases.length - t;

    //基类数组里的第一个对象
    superclass = bases[mixins];
}else{

    //只有一个基类的情况
    bases = [0];
    if(superclass){
        if(opts.call(superclass) == "[object Function]"){
            t = superclass._meta;
            bases = bases.concat(t ? t.bases : superclass);
        }else{
            err("base class is not a callable constructor.");
        }
    }else if(superclass !== null){
        err("unknown base class. Did you use dojo.require to pull it in?")
    }
}

//开始构造基类属性,合并他们的prototype内容
if(superclass){
    for(i = mixins - 1;; --i){

        //拷贝prototype ,superclass为基类数组里的第一个函数对象,forceNew之后变成含有superclass的prototype   属性的一个对象
        proto = forceNew(superclass);
        if(!i){
            // stop if nothing to add (the last base)
            break;
        }
        // mix in properties
        t = bases[i];

        //合并所有基类的prototype,作为后面子类的prototype,实现属性共享
        (t._meta ? mixOwn : mix)(proto, t.prototype);
        //构造 基于合并prototype的基类临时函数对象
        ctor = new Function;
        ctor.superclass = superclass;
        ctor.prototype = proto;

       
        superclass = proto.constructor = ctor;

        //如上这行代码用于调整所构造的ctor的constructor,保持一致性,然后修改superclass用于后续迭代,其实将这一行写成如下两行更通俗易懂:

        //      ctor.prototype.constructor = ctor;

                //      superclass = ctor;


    }
}else{
    proto = {};
}

.................

 

 

 

这里我们只是粗略的把dojo.declare的主线路大致过了一遍,后面附上了dojo.declare的源代码(基于dojo1.5),大家可以参考一下。关于dojo.declare的实现细节还有很多很多值得讨论的地方,但是这里由于篇幅过长,所以关于dojo的面向对象机制的详细实现我们以后再继续讨论,这里就不做详细说明了。

 

dojo.declare 是和 dojo.require(类似java的import) 以及 dojo.provide 联合起来一起使用的,主要由这3个函数将javascript封装成了一个接近面向对象的dojo语言模式,这也是dojo比起其他web控件库比较独到的一大特点。

 

另外强调一点:在dojo.declare方法里还实现了一种比较有用的链式机制,通过定义“-chains-”变量来使用,有兴趣可以研究一下,这里不做过多说明。

 

 

 

 

 

 

 

 

附上dojo.declare源代码:(dojo1.5)

 

d.declare = function(className, superclass, props){
        // crack parameters
        if(typeof className != "string"){
            props = superclass;
            superclass = className;
            className = "";
        }
        props = props || {};

        var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass;

        // build a prototype
        if(opts.call(superclass) == "[object Array]"){
            // C3 MRO
            bases = c3mro(superclass);
            t = bases[0];
            mixins = bases.length - t;
            superclass = bases[mixins];
        }else{
            bases = [0];
            if(superclass){
                if(opts.call(superclass) == "[object Function]"){
                    t = superclass._meta;
                    bases = bases.concat(t ? t.bases : superclass);
                }else{
                    err("base class is not a callable constructor.");
                }
            }else if(superclass !== null){
                err("unknown base class. Did you use dojo.require to pull it in?")
            }
        }
        if(superclass){
            for(i = mixins - 1;; --i){
                proto = forceNew(superclass);
                if(!i){
                    // stop if nothing to add (the last base)
                    break;
                }
                // mix in properties
                t = bases[i];
                (t._meta ? mixOwn : mix)(proto, t.prototype);
                // chain in new constructor
                ctor = new Function;
                ctor.superclass = superclass;
                ctor.prototype = proto;
                superclass = proto.constructor = ctor;
            }
        }else{
            proto = {};
        }
        // add all properties
        safeMixin(proto, props);
        // add constructor
        t = props.constructor;
        if(t !== op.constructor){
            t.nom = cname;
            proto.constructor = t;
        }

        // collect chains and flags
        for(i = mixins - 1; i; --i){ // intentional assignment
            t = bases[i]._meta;
            if(t && t.chains){
                chains = mix(chains || {}, t.chains);
            }
        }
        if(proto["-chains-"]){
            chains = mix(chains || {}, proto["-chains-"]);
        }

        // build ctor
        t = !chains || !chains.hasOwnProperty(cname);
        bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
            (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));

        // add meta information to the constructor
        ctor._meta  = {bases: bases, hidden: props, chains: chains,
            parents: parents, ctor: props.constructor};
        ctor.superclass = superclass && superclass.prototype;
        ctor.extend = extend;
        ctor.prototype = proto;
        proto.constructor = ctor;

        // add "standard" methods to the prototype
        proto.getInherited = getInherited;
        proto.inherited = inherited;
        proto.isInstanceOf = isInstanceOf;

        // add name if specified
        if(className){
            proto.declaredClass = className;
            d.setObject(className, ctor);
        }

        // build chains and add them to the prototype
        if(chains){
            for(name in chains){
                if(proto[name] && typeof chains[name] == "string" && name != cname){
                    t = proto[name] = chain(name, bases, chains[name] === "after");
                    t.nom = name;
                }
            }
        }
        // chained methods do not return values
        // no need to chain "invisible" functions

        return ctor;    // Function
    };

液晶屏LVDS接口:【图文详讲】 ​LVDS(Low Voltage Differential Signaling,即低电压差分信号)接口又称RS-644总线接口,是20世纪90年代才提出的一种数据传输和接口技术。LVDS接口是美国NS美国国家半导体公司为克服以TTL电平方式传输宽带高码率数据时功耗大,电磁干扰大等缺点而研制的一种数字视频信号传输方式 阅读详情

相关推荐

VS2017中调用gdal(C#版)的方法二(含gdal下载地址,配置过程,代码测试,超详细!!)

VS2017中gdal(C#)版的配置与测试 上次记录了直接在VS2017中下载并应用gdal的方法,这次来记录一下网上下载的安装包配置与测试的方法。 一、环境、版本及下载地址 win10,vs2017社区版,gdal2.4.4 还是像之前在Unity中应用gdal一样,最好是下载已经编译好的C#版的gdal,不然自己配置真的很容易出错,我就是这样的,下面提供不同版本的gdal下载地址: 1.GDAL2.4.4(C#版、64位): https://download.youkuaiyun.com/download/che

chengbaola的博客 1365

Dojo学习和常用知识

Dojo 是一个流行的 JavaScript 库,用于开发 Web 应用程序。它提供了许多功能,如 DOM 操作、事件处理、动画效果、数据存储和许多其他实用功能。在今天的 Web 开发中,Dojo 仍然被广泛使用,尤其是在企业级应用程序开发中。下面是一个详细的 Dojo 详解,包括代码实例。

AI时代光年 1753

避开PFC设计大坑:从环路分析到参数整定的5个常见误区与解决方案

本文深入解析PFC电路设计中从环路分析到参数整定的5个常见误区,包括电感参数设计、小信号模型适用边界、电压环与电流环耦合效应等。通过实际案例和PSIM仿真数据,提供工程落地的解决方案,帮助工程师避开设计陷阱,提升电路性能与可靠性。

weixin_30666401的博客 325

dojo事件机制详解(一)

概述 dojo中的事件实现并不复杂,当然我只是从代码量的角度出发,但含金量还是很高的,而且很容易实现自定义事件监听,还支持发布订阅模式,下面我们从源代码级别来看看 dojo中的事件机制是如何实现的,深入了解后,甚至可以将其拷贝出来直接就能在其它使用。 事件机制使用中主要涉及以下4个函数: 1. dojo.connect(); 建立事件监听连接 2. dojo.disconnect();

云原生之家 3223

HDRP shader 获取阴影(Custom Pass)

Unity:2021.3.0f1 HDRP:12.1.6

LanQ的博客 2098

【爬虫】Python实现爬取淘宝商品信息(超详细)

项目基于Python的第三方库Selenium模拟浏览器运行、PyQuery解析和操作HTML文档,获取淘宝平台中某类商品的详细信息(商品标题、价格、销量、商铺名称、地区、商品详情页链接、商铺链接等),并基于第三方库openpyxl建立、存储于Excel表格中。# 全局变量count = 1 # 写入Excel商品计数# 启动ChromeDriver服务# 关闭自动测试状态显示 // 会导致浏览器报:请停用开发者模式# 把chrome设为selenium驱动的浏览器代理;# 窗口最大化。

qq_46315152的博客 4万+

dojo框架的基本认识

Dojo的全称是Dojo Toolkit,始创于2004年,是当前各种蓬勃发展的JS工具包中的佼佼者。Dojo 为富互联网应用程序(RIA) 的开发提供了完整的端到端的解决方案,包括核心的 JavaScript 库,简单易用的小部件(Widget)系统和一个测试框架,此外,Dojo 的开源开发社区还在不停地为它提供新的功能。

weixin_45774558的博客 3133

Python 爬虫实战:微博自动化运营工具(点赞 / 转发 / 评论 + 反封号策略)

微博作为中国最大的社交媒体平台之一,拥有庞大的用户群体和丰富的数据资源。通过 Python 爬虫技术,我们可以实现微博的自动化运营,包括点赞、转发、评论等功能,同时采取有效的反封号策略,确保账号的安全和稳定运行。

u014481728的博客 1178

dojo 移动应用_编写定制的Dojo应用程序

我们最近完成了Web 2.0 Dojo原型的开发。 该原型非常广泛,为信息管理提供了新功能。 我们与用户体验团队合作,以确保应用程序可用。 屏幕是由图形Web设计人员设计的,具有专业的外观。 本文记录了我们对该原型的Web 2.0开发的经验。 因为Web 2.0是相对较新的,所以在需要时可能很难入门或不知道如何进行自定义。 我们的Dojo应用程序没有提供开箱即用的外观。 我们需要一个与我们...

cuyi7076的博客 666

YOLOv11【第一章:零基础入门篇·第10节】YOLOv11项目实战:从零搭建检测系统!

🏆 本文收录于专栏 《YOLOv11实战:从入门到深度优化》。本专栏围绕 YOLOv11 的改进、训练、部署与工程优化 展开,系统梳理并复现当前主流的 YOLOv11 实战案例与优化方案,内容目前已覆盖 分类、检测、分割、追踪、关键点、OBB 检测 等多个方向。

**My Coding Family** 5770

【C++】开源:ncurses终端TUI文本界面库

ncurses配置使用(TUI)

DevFrank的博客 3168

Dojo

dojo的类机制支持类声明、继承、调用父类方法等功能。dojo在底层实现上是通过操作原型链来实现其类机制的,而在实现继承时采用类式继承的方式。值得一提的是,dojo的类机制允许进行多重继承(注意,只有父类列表中的第一个作为真正的父类,其它的都是将其属性以mixin的方法加入到子类的原型链中),为解决多重继承时类方法的顺序问题,dojo用JavaScript实现了Python和其它多继承语...

dianxuanfan4560的博客 337

FLACS-CFD 气云爆炸模拟全流程工况构建指南:从泄漏到爆炸

摘要: 本文详细介绍了使用FLACS-CFD模拟气云爆炸的全流程构建方法,重点解决泄漏模拟到爆炸模拟的气云文件传递问题。核心步骤包括: 项目规划:明确泄漏源(甲烷管道腐蚀泄漏)和爆炸场景,建立标准目录结构; 网格设计:泄漏与爆炸模拟需采用兼容的网格,爆炸域应为泄漏域的子区域且网格划分一致; 泄漏模拟配置:通过.inp文件定义几何、网格、风场、燃料及泄漏源参数,确保输出爆炸所需的气云文件(*.uni/*.fla); 关键设置:统一燃料名称、时间点匹配、路径正确性,避免版本兼容性问题。

huanghm88的专栏 762

ESP32多应用Flash存储隔离:从分区表到NVS的完整方案

在嵌入式开发中,Flash 存储管理是保障多应用稳定运行的关键。ESP32 的存储资源由分区表统一规划,每个分区如同独立的“房间”,用于存放固件、配置或日志。若分区划分不当或代码越界写入,轻则数据错乱,重则系统启动失败。NVS(非易失性存储)作为轻量级键值存储,通过命名空间实现了逻辑隔离;而 LittleFS 等文件系统则为大块日志和升级包提供高效的物理分区管理。无论是智能家居中的多传感器协作,还是工业设备上的参数校准与 OTA 升级,合理利用分区表、NVS 命名空间和文件系统,能有效避免数据“串门”,提升

weixin_34320724的博客 306

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

DOJO中的面向对象__第四章 Dojo/_base/declare.js源码剖析(1)

  declare.js中包含了整个dojo面向对象中最重要的代码,即对类型表达和扩展的一些封装。功能虽然强大,但是幸好文件并不复杂,拥有清晰的脉络。整个declare.js一共定义了15个函数,14个具名函数,1个匿名函数。这14个具名函数中又有一些是declare.js内部使用的函数,外部无法调用,还有一些是由dojo提供的接口,可以供dojo.declare声明的类型来调用。具体函数如下所示...

driftcloudy的专栏 251

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Dojo:不容忽视的RIA框架

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33815613的博客 428

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

DOJO中的面向对象__第五章 Dojo/_base/declare.js源码剖析(2)

接着第四章.... (二)   getInherited和inherited方法   这两个方法是对外提供的扩展接口,可以用declare出来的类型的实例调用。它们的用途是返回父类中曾经出现的方法,或者对其进行调用。具体的用法在第二章中已经描述,这里不再举例说明。   1. getInherited方法主要用来返回父类中的方法;   2. inherited方法主要用来调用父类中的方法...

driftcloudy的专栏 247

JavaScript instanceof 运算符深入剖析

instanceof 运算符简介 在 JavaScript 中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "object"。ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。instanceof 运算符与 typeof 运算符相似,用于识别正在处...

包磊磊的博客 445

instanceof深入剖析

随着 web 的发展,越来越多的产品功能都放在前端进行实现,增强用户体验。而前端开发的主要语言则是 JavaScript。学好 JavaScript 对开发前端应用已经越来越重要。在开发复杂产品中,需要使用面向对象的机制时,往往会用到复杂的 JavaScript 继承,而 instanceof 运算符是 JavaScript 语言中原生的用来判断实例继承关系的操作符。深入理解 instance

明天回火星 429
上一篇: 如何根据类名和参数创建对象
下一篇: Dojo历史简介
dojotoolkit
博客等级 码龄16年 1205粉丝 61原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值