dojo 开发资源

什么是面向对象的开发?

发展有关此主题的技能

此内容是用于提高技能的渐进知识路径的一部分。 请参阅Dojo开发入门

面向对象编程(OOP)是一种软件开发范例,其基于称为对象的数据结构的定义,该结构由数据属性和功能组成。 这些属性(成员变量)和功能(或方法)定义了软件可以与该对象执行的潜在交互。 OOP的主要好处是,通过简化代码的组织,它有助于代码的重用和维护。

面向对象的基础

面向对象编程的基本前提是,您可以在软件中创建对象,这些对象定义适用于该对象的一系列属性以及可以检索或修改该对象属性的一系列方法或函数。 一个简单的物体示例可能是car 。 与car关联的数据属性可能包括其manufacturermodel numberregistration numbercolorcubic capacity等。 您可能会找到提供car对象的方法,包括acceleratebrakechange gearturnstop等。 在OOP中,想法是定义所有汽车共有的基本属性和方法,然后每辆汽车将采用该定义的形式,尽管彼此之间的值互不相同。 正如您将在本文后面看到的那样,软件开发中有多种类型的面向对象方法。

通用的OOP术语

为了充分利用本文,您至少应该熟悉面向对象的编程及其概念。 以下是讨论面向对象的开发时使用的一些常用术语的基本描述。 值得指出的是,并非所有类型的OOP都包含所有这些方面。 例如,基于原型的对象语言(例如JavaScript)中没有类。

在基于类的面向对象的开发中,类定义了组成对象的不同属性和功能。 该类定义了从中生成对象的模板,因此它们应定义这些对象可以遵循的通用属性和操作。 一个类通常由成员变量和方法组成。

成员变量

对象的成员变量是对象的属性或属性。 在我之前提供的汽车示例中,这些属性可能包括诸如汽车manufacturermodelcolorcubic capacity等内容。

方法

方法是对象可以执行的动作。 例如,汽车可以acceleratebraketurn等等。 通常,方法会修改成员变量的值。 例如,当car对象使用accelerate方法accelerate其当前速度属性将增加。 许多对象将具有称为构造函数的特殊方法,该方法在创建对象时总是立即调用。

实例或对象

实例或对象是实际的对象本身,而不是用于定义对象的模板。 例如,您可能有一个名为myCar的对象,该对象具有汽车模板的属性和方法。 在对象的实例中,属性实际上将具有值。 因此,例如, myCar的颜色属性可能是silver ,立方容量属性是2500 。 对象属性的当前值称为其状态,并且其状态可以在对象的整个生命周期中发生变化。

遗产

在基于类的OOP中,继承是子类或子类继承其超类或父类的成员变量和方法的过程。 除了继承这些属性和动作,子类还可以定义自己的成员变量和方法,并为父类的属性提供默认值。 例如,您可能有一个FourByFour类,它是Car类的子类。 该子类可以将其超类的驱动系统属性设置为默认为4WD (四轮驱动)。 此外,它可以使用仅适用于4x4车辆的名称传递大小写定义另一个属性,以及一种可以更改常规车辆不可用的低档档位的方法。

封装形式

在基于类的OOP中,成员变量通常被声明为私有变量,因此无法在类本身的范围之外进行访问或修改。 有一些称为修饰符的特殊方法,可让您定义一些方法,这些方法将检索或修改类中私有成员函数的值。 这些方法(通常称为getter和setter)使程序员可以使用信息隐藏来仅使应用程序和其他类可以访问某些属性。 此技术通常称为封装。

抽象化

抽象是通过仅定义对对象在当前上下文中重要的属性和方法来降低对象复杂性的过程。 例如,在定义Car类时,可以通过定义汽车具有的所有其他货车(例如货车,卡车,摩托车等)的所有属性,进一步将该类抽象为Vehicle类。 然后, Car类将从Vehicle类继承这些属性, Motorcycle类或Van类也将继承这些属性。

多态性

在OOP上下文中,多态性意味着子类可以从其超类继承方法,而不必为所有事物提供相同的实现。 举一个例子,您可能有两个Car类的子类,一个子类用于自动变速箱的汽车(简称ATCar ),另一个子类用于手动变速箱的汽车(例如MTCar )。 所有的Car对象都可以加速,因此ATCarMTCar都将从父类继承accelerate方法。 但是,在ATCar当发动机达到一定转速时,您的加速方法会自动调用换挡方法。 其结果是,你重写的父类的定义accelerate的方法ATCar子类,而在MTCar方法将保持相同,它从继承的一个Car类。

本文并不旨在作为面向对象编程的全面指南。 如果您对上面概述的概念不满意,那么在继续本文之前,最好跳到“ 相关主题”并阅读有关OOP的更多信息。

面向对象JavaScript

上一节中介绍的许多概念是特定的OOP范例所专有的,这些范例称为基于类的面向对象编程。 但是,并非所有的编程语言都遵循这种范例。 OOP的另一种常见类型是基于原型的面向对象,这是JavaScript语言中使用的范例。 在本部分中,您将学到更多有关JavaScript的面向对象的实现,如何使用它的示例以及可能会遇到的一些绊脚石的信息,特别是如果您来自基于类的OOP背景。

JavaScript不仅是一种基本的脚本语言

当JavaScript首次流行时,它主要被用作在基本网页上执行简单技巧的一种手段。 使用JavaScript的大多数人不是软件开发人员,而是图形或Web设计师,他们可能有很多HTML方面的经验,但是对编程语言的了解很少或没有。 就允许某人产生动态效果而言,HTML本身非常有限,这就是JavaScript发挥作用的地方。 但是,大多数设计人员不会真正学习如何使用JavaScript进行编程,而只是找到他们所需的代码片段,学习足够的知识以知道如何根据自己的特定需求对其进行调整,然后使用那小段代码。 当设计人员经过多次此过程时,他们会感到他们具有可接受JavaScript知识水平。

在网络的早期,JavaScript十分有限。 但是,它已经发展成为一种成熟且功能齐全的编程语言,它不再只是用来为网站编写简单的技巧,而是为整个富Internet应用程序提供动力。 实际上,如今,JavaScript也已以其他各种方式使用。 例如,CouchDB面向文档的数据库管理系统使用JavaScript函数来查询数据库中的数据。

许多Java开发人员(以及使用其他更传统的编程语言的开发人员)可能看不起JavaScript,并将其视为基本的脚本语言。 尽管JavaScript已经发展成为功能非常强大的工具,但人们仍将其当作只是用来欺骗网站的心态。 这是因为大多数使用JavaScript的Web开发人员将使用jQuery,Prototype或Dojo之类的库和框架来减轻为他们编写JavaScript的痛苦。 实际上,许多Web开发人员可以被认为是编写jQuery应用程序的专家,但实际上对JavaScript本身的专业知识很少。 这些开发人员中许多人所缺少的是,香草JavaScript实际上非常强大,并且包括开箱即用的面向对象功能。 在本节中,您将了解这些功能。

基于原型的OOP

JavaScript实现了一种不同于Java™代码的面向对象编程。 Java编程基于基于类的OOP模型,而JavaScript基于基于无类的OOP模型,通常称为基于原型的面向对象。 无需定义从中创建对象的一组类模板,而是在需要时仅声明对象。 当一个对象需要从另一个对象继承特征时,它可以简单地克隆原型对象的特征。 原型OOP的关键优势之一是可以在运行时修改对象原型,这意味着对象结构的定义不严格。 大多数基于类的OOP编程语言都不允许在运行时动态更改类(尽管有一些例外,例如Perl,Python和Ruby)。

在下一部分中,您将学习如何使用原型模型在原始JavaScript中使用OOP。

原始JavaScript中面向对象的示例

在本系列文章的第1部分中,您了解了Firefox的Firebug插件,以及如何使用控制台来运行JavaScript代码,而不必编辑,保存和运行文件以及在网页上执行事件。 打开Firefox并启动Firebug。 您当前在哪个网页上都没有关系,因为此示例不需要任何特定JavaScript库。

您可以创建一个将用作对象原型的函数,而不是在JavaScript中声明类。 然后,您可以使用new关键字创建此对象的实例。 有关此示例,请在Firebug控制台中输入清单1中的代码:

清单1. JavaScript中的基本对象原型
function Car() { }var myCar = new Car();
console.log(myCar);

这将在控制台日志中产生以下输出: Object {}

您实际上可以单击此输出,它将带您进入Firebug的另一部分,可让您检查对象的各种属性。 如果单击该特定对象,则会看到一条消息“该对象没有要显示的属性”。

该代码实际在做什么是定义一个对象函数Car() 。 然后,它使用new运算符实例化一个对象,最后,将该对象输出到Firebug控制台,您可以在其中进一步检查它。 但是,这个对象几乎不会使世界正确,因此让我们使其更加有趣(请参见清单2)。

清单2.在对象中定义一个成员变量
function Car() { }
Car.prototype.current_speed = 0;var myCar = new Car();
console.log(myCar);

这次,控制台日志将输出一些更有趣的东西: Object { current_speed=0 }

单击输出将带您回到DOM检查器窗口,您可以在其中看到属性current_speed和值为0 。 默认情况下,使用Car原型函数创建的任何对象都将具有current_speed属性,默认值为零。

如果汽车无法加速,它几乎是无用的,因此让我们为原型添加一个方法(参见清单3)。

清单3.在原型中添加一个方法
function Car() { }
Car.prototype.current_speed = 0;
Car.prototype.accelerate = function(increment) {this.current_speed += increment;
}var myCar = new Car();
myCar.accelerate(30);
myCar.accelerate(20);console.log(myCar);

控制台输出应产生以下内容: Object { current_speed=50 }

单击输出将不仅显示current_speed属性,而且显示对象可用的新的accelerate方法。 在清单3的示例中,您可以看到如何调用对象的方法:使用点表示法,例如object.method(arg[0], arg[1], ..., arg[N]) ; 在这种情况下,它是myCar.accelerate(20) 。 可以使用相同的符号来访问对象的任何特定属性。 将行console.log(myCar)更改为console.log(myCar.current_speed) ,您应该看到控制台输出显示值50而不是实际对象本身的表示。

接下来,让我们研究如何在JavaScript中实现构造函数。 构造函数是在实例化对象后立即调用的函数。 创建对象函数时,它可以兼用作构造函数。 清单4是一个实际的例子。

清单4.添加一个构造函数主体
function Car(reg_no) { this.reg_no = reg_no;console.log('Car with registration no. '+this.reg_no+' created.');
}Car.prototype.reg_no = '';
Car.prototype.current_speed = 0;
Car.prototype.accelerate = function(increment) {this.current_speed += increment;
}var myCar = new Car('10C500');
myCar.accelerate(30);
myCar.accelerate(20);console.log(myCar.current_speed);

在清单4中, Carconstructor函数接受一个参数作为其注册号。 然后,它将对象实例的注册号设置为参数值,并向Firebug控制台输出一条消息,以确认实例已创建。 您应该在Firebug控制台输出窗口中看到清单5中的输出。

清单5.输出
Car with registration no. undefined created.
50

为了演示如何在对象原型上实现继承,让我们创建一个更高级的Car原型,其中包含用于加速,减速和更改齿轮的方法(参见清单6)。

清单6.一个更完整的Car原型
function Car(reg_no) { this.reg_no = reg_no;
}Car.prototype.reg_no = '';
Car.prototype.current_speed = 0;
Car.prototype.current_gear = 0;Car.prototype.accelerate = function(increment) {this.current_speed += increment;
}
Car.prototype.decelerate = function(decrement) {this.current_speed -= decrement;
}
Car.prototype.increaseGear = function() {this.current_gear++;
}
Car.prototype.decreaseGear = function() {this.current_gear--;
}

现在让我们从这个名为ATCar的继承对象原型中创建一个原型,该原型描述具有自动变速器的汽车。 这个特定示例并不是完美的汽车,因为它基于速度而不是RPM实现变速,但是它应该有助于在原型OOP中获得继承和多态的想法(参见清单7)。

清单7.一个继承自CarATCar对象原型
function ATCar(reg_no) {Car.call(this, reg_no);
}
ATCar.prototype = new Car();
ATCar.prototype.constructor = ATCar;ATCar.prototype.accelerate = function(increment) {Car.prototype.accelerate.call(this, increment);if(increment >= 10) this.increaseGear();
}ATCar.prototype.decelerate = function(decrement) {Car.prototype.decelerate.call(this, decrement);if(this.current_speed === 0) this.current_gear = 0;else if(decrement >= 10) this.decreaseGear();
}

您会注意到的第一件事是,构造函数在Car对象原型上使用了call函数。 每当实例化ATCar时,这基本上将在父原型定义上调用构造函数。 这使您可以确保实现继承,而ATCar原型不需要了解Car对象原型的内部工作原理。 接下来,您将看到将ATCar函数的prototype属性设置为Car函数的新实例。 这基本上告诉JavaScript您想继承ATCar原型中Car原型的属性和方法。

在清单7中,您还将覆盖acceleratedecelerate方法,以便在自动汽车上,加速和减速也会使齿轮自动改变。 在这两种方法中,您首先要调用父原型的方法,因此不必重新实现实际的加速,从而节省了重复的代码。 在此特定示例中,这并不是那么重要,因为它只是一行代码,但可以想象这是一个复杂的函数; 重复它会很痛苦!

最后,让我们看一下这个示例(参见清单8)。

清单8.使用自动汽车原型
var myCar = new ATCar('10C500');
myCar.accelerate(30);
myCar.accelerate(20);
myCar.decelerate(5);console.log(myCar);

这将输出您创建的新对象。 单击对象以查看其详细信息。 结果应该类似于图1。

图1. myCar对象属性的Firebug视图

本文的主要目的是向您展示如何使用Dojo的基于类的OOP仿真功能,因此,这仅仅是Vanilla JavaScript的面向对象原型方法的介绍。 有关基于原型的OOP的更多信息,请参阅参考资料 。

原型OOP的问题

对于基于原型的面向对象编程是优于还是劣于基于类的OOP,不同的人有不同的看法。 根据您作为程序员的喜好,可以很容易地反驳支持或反对的每个论点。 基于原型的对象定向(尤其是在JavaScript中)最常见的问题之一是缺乏许多开发人员对其的基本了解。 然而,随着对JavaScript有深刻理解的开发人员的数量稳步增加,这逐渐变得不那么重要。 话虽如此,许多熟悉基于类的OOP语言(例如Java语言)的程序员仍然会喜欢坚持使用基于类的系统,而Dojo提供了一些出色的功能来模拟这种类型的系统,以使您可以使用JavaScript编写代码。类似的方式。 下一节将说明如何使用Dojo的这些功能在JavaScript中创建基于类的应用程序。

使用Dojo模拟基于类的OOP

在进一步讨论Dojo的基于类的仿真之前,需要注意的一点是,归根结底,Dojo仍然是一个JavaScript库。 Java代码和JavaScript不相同; 实际上,它们是完全不同的。 Dojo并不试图强迫JavaScript像Java代码一样工作,而是允许您以Java(以及其他基于类的OOP语言)开发人员更熟悉的方式使用JavaScript OOP,而其底层结构仍在运行原型时尚。

使用dojo.declare创建类

要使用Dojo创建类,请使用dojo.declare函数。 现在,使用此函数创建一个Car类(请参见清单9)。

清单9.使用dojo.declare创建一个Car
dojo.declare("Car", null, {});var myCar = new Car();
console.log(myCar);

这是创建类和实例化该类对象的基本外壳。 dojo.declare函数接受三个参数:

  1. 班级名称
  2. 该类应继承的超类
  3. 包含该类的任何属性和方法的对象

在清单9的示例中,您声明了一个名为Car的类,该类没有继承任何超类,并且没有规定任何成员变量或方法。 如果通过在Firebug控制台中单击输出来查看myCar对象的对象属性,则应该看到类似于图2的内容。

图2.从Dojo类创建的基本对象

如您所见,在Dojo中创建一个类将默认为从该类生成的任何对象提供一些属性和方法。 您当前的类不是很有趣,所以让我们添加一些属性和方法以及一个构造函数,就像您在上一节中演示面向原型的方法那样(参见清单10)。

清单10.更完整的Car
dojo.declare("Car", null, {reg_no: "",current_speed: 0,current_gear: 0,constructor: function(reg_no) {this.reg_no = reg_no;},accelerate: function(increment) {this.current_speed += increment;},decelerate: function(decrement) {this.current_speed -= decrement;},increaseGear: function() {this.current_gear++;},decreaseGear: function() {this.current_gear--;}
});

如您所见,与普通JavaScript声明对象原型的方式相比,这种类型的类声明更易于阅读并且组合在一起。 在继续继承之前,让我们检查一个对象可以实例化并且方法可以工作(参见清单11)。

清单11.使用Car
var myCar = new Car("10C500");
myCar.accelerate(30);
myCar.accelerate(20);
myCar.decelerate(5);
console.log(myCar.reg_no+" travelling at "+myCar.current_speed+" mph");

这将在Firebug控制台中产生以下输出: 10C500 travelling at 45 mph

继承和多重继承

接下来,像以前使用普通JavaScript一样创建自动传输子类,但是这次使用dojo.declare函数(参见清单12)。

清单12.使用Dojo创建ATCar子类
dojo.declare("ATCar", Car, {accelerate: function(increment) {this.inherited(arguments);if(increment >= 10) this.increaseGear();},decelerate: function(decrement) {this.inherited(arguments);if(decrement >= 10) this.decreaseGear();}
});

从清单12中可以看到,子类中唯一提供的是任何重写的或新的属性和方法(在这种情况下,您只是重写了加速和减速方法以自动更改齿轮)。 Dojo负责自动调用超类中的构造函数。 如果需要添加构造函数,则可以向子类添加构造函数,但是不必担心调用超类构造函数。 这是自动完成的。 您会注意到,在这两个覆盖的方法中,都调用了this.inherited(arguments)行。 这将基本上调用超类中的相同方法。 这样就可以避免编写代码来进行实际加速,而仅像自动汽车提供的那样方便换档。

让我们检查一下正在使用的新子类(请参见清单13)。

清单13.运行中的新子类
var myCar = new ATCar("10C500");
myCar.accelerate(30);
myCar.accelerate(20);
myCar.decelerate(5);
console.log(myCar.reg_no+" travelling at "+myCar.current_speed+" mph in gear "+myCar.current_gear);

这将产生以下输出: 10C500 travelling at 45 mph in gear 2

Dojo还包括对多重继承的支持。 多重继承允许从多个父类派生一个子类,并从每个父类继承属性和方法。 严格来讲,这些父类中只有一个被认为是超类(数组中的第一个),但是每个派生类的构造函数将按照它们在父类数组中的驻留顺序被调用。

为了说明多重继承,以智能手机为例,它不仅执行电话和短信接收功能,还执行许多功能(参见清单14)。 通常,它还将执行诸如播放音乐,观看视频等功能。 就本示例而言,让我们保持简单,并说一个电话可以拨打电话,一个MediaPlayer可以播放视频,而一个智能手机可以同时进行。

清单14. Dojo中的多重继承
dojo.declare("Phone", null, {phone_number: "",minutes_remaining: 0,constructor: function(properties) {this.phone_number = properties.phone_number;this.minutes_remaining = properties.minutes_remaining;console.log("Phone "+this.phone_number+" powered on. You have
"+this.minutes_remaining+" minute(s) remaining.");}
});dojo.declare("MediaPlayer", null, {disk_space: 0,constructor: function(properties) {this.disk_space = properties.disk_space;this.songs = properties.songs;console.log("Media Player powered on. You have "+this.songs.length+" songs,
with "+this.disk_space+" GB free space left.");}
});dojo.declare("Smartphone", [Phone, MediaPlayer], {phone_id: "",constructor: function(properties) {this.phone_id = properties.phone_id;console.log("Smartphone ID "+this.phone_id+" boot up complete.");}
});var songs = [{artist:"U2",title:"Vertigo"},{artist:"Coldplay",title:"Yellow"}
];var myPhone = new Smartphone({phone_number:"(555) 123-4567", minutes_remaining: 60, disk_space: 2.5, songs: songs,phone_id: "4345FDFD7JAPO76"
});console.log(myPhone);

值得指出的第一件事是dojo.declare如何实现多重继承。 如您所见,不仅传递父类作为第二个参数,还传递了一个类数组。 这些父类的构造函数将按照它们在数组中出现的顺序自动调用。 需要注意的重要一点是,如果每个父类构造函数都接受不同的参数,Dojo将无法区分应传递给每个构造函数的参数。 因此,如果确实需要将不同的参数传递给不同的构造函数,则应在简单JavaScript中将这些参数作为键/值对添加,并以这种方式在构造函数中使用它们。

清单15是将显示在Firebug控制台中的输出。

清单15.多重继承示例输出
Phone (555) 123-4567 powered on. You have 60 minute(s) remaining.
Media Player powered on. You have 2 songs, with 2.5 GB free space left.
Smartphone ID 4345FDFD7JAPO76 boot up complete.
Object { phone_number="(555) 123-4567", more...}

单击最后一行中的链接将显示myPhone对象的属性,其外观应类似于图3。

图3. myPhone对象,从多个父类继承

在图3中,智能手机类的实例化对象中都存在不同类的不同属性。 还有Phone类的phone_numbermintues_remaining属性,还有MediaPlayer类的disk_spacesongs ,还有Smartphone子类的phone_id成员变量。 如果这些类中的任何一个都有方法,这些方法也将显示在这里。

使用dojo.mixin改进多继承示例

Dojo提供了一个不错的实用程序函数dojo.mixin ,它使您可以通过从左到右组合对象的属性来混合对象(参见清单16)。

清单16. dojo.mixin的基本示例
var objA = { a: 1, b: 2 };
var objB = { b: 3, c: 4 };
dojo.mixin(objA, objB);
console.log(objA);

混合后objBobjA ,在属性objA看起来如图4所示。

图4.使用dojo.mixin混合对象

b ,最初设置为属性2objA ,已被覆盖与值3objB 。 此外,还添加了c属性。 在完成基本示例之后,让我们看一下如何在多重继承示例中使用dojo.mixin

在上一个示例中创建Phone类时,您可能会在该类的构造函数中调用清单17中的两行。

清单17. Phone类构造函数中的行
this.phone_number = properties.phone_number;
this.minutes_remaining = properties.minutes_remaining;

这并不是很乏味,因为只有2个属性,但是如果还有更多属性该怎么办? 以这种方式分配属性不是很痛苦吗? 这就是dojo.mixin函数真正有用的地方。 用以下行替换这两行(以及MediaPlayerSmartphone类中的类似行): dojo.mixin(this, properties);

结果与之前完全相同,但是不会弄乱已传递给构造函数的各种属性。 整洁吧?

Dojo的包装和模块化开发

当使用大型应用程序时,您可能会拥有包含许多成员变量和方法的大型类。 如果您来自Java开发背景,那么您很有可能会遵循这样的观念,即不同的类应该驻留在按包分组的不同文件中。 然后,在出于继承或其他目的而需要时,将类“导入”,以确保仅在必要时才加载类。 使用JavaScript时,没有现成的包装和模块系统,但值得庆幸的是,Dojo提供了一个解决方案。

例如,在Car类示例中,可以使用Java代码将其存储在一个包中,如清单18所示。

清单18. Java编程中的包装类
package com.ibm.developerworks.dojoseries;
public class Car {//Car class code goes here
}

您稍后可以将该类导入其他Java类,如清单19所示。

清单19.在Java编程中导入类
package com.ibm.developerworks.dojoseries;
import com.ibm.developerworks.dojoseries.Car;
public class ATCar extends Car {//ATCar class code goes here
}

Dojo通过dojo.providedojo.require函数提供了类似的打包系统。 让我们看一下清单19中的Java代码在Dojo中的外观。 首先,让我们看看清单20中的Car类。

清单20. Dojo中的打包类
dojo.provide("com.ibm.developerworks.dojoseries.Car");
dojo.declare("com.ibm.developerworks.dojoseries.Car", null, {//Car class code goes here
});

您可能会注意到,这与Java代码非常相似,尽管该类的整个包路径都在dojo.provide语句中给出,而不仅仅是包含包的路径。 包路径很重要,因为它还确定了Dojo在尝试使用dojo.require加载该类时将在哪里寻找该类。 因此,对于清单20中的示例,Car.js文件应存储在相对路径com / ibm / developerworks / dojoseries / Car.js中。 如果未将其存储在此位置,Dojo将无法在需要时正确加载该类。 接下来,让我们看一下如何导入此类并从中创建一个子类(参见清单21)。

清单21.在Dojo中导入类
dojo.provide("com.ibm.developerworks.dojoseries.ATCar");
dojo.require("com.ibm.developerworks.dojoseries.Car");
dojo.declare("com.ibm.developerworks.dojoseries.ATCar", com.ibm.developerworks.dojoseries.Car, {//ATCar class code goes here
});

您会在这里注意到,您再次使用dojo.provide语句来标识可以从中加载此类的路径。 该特定类将存储在相对路径com / ibm / develoeprworks / dojoseries / ATCar.js中。 接下来,使用dojo.require通过其完整的包路径加载Car类。 最后,您声明子类,并将完整路径传递给父类作为第二个参数。 因为此类已由Dojo加载,所以它在DOM中可用,并且可以通过其名称直接加载,而无需将其放在字符串中。

尽管从技术上讲,您可以使用与dojo.provide语句中提供的路径不同的类名(请注意,使用dojo.require任何类加载都必须使用dojo.provide设置的标准路径),但强烈建议您使用不要这样做,因为这只会导致混乱。

下一节将说明如何使用Dojo的构建系统打包应用程序,以确保其以最佳性能和速度运行。

全部打包-使用Dojo的构建系统

使用Dojo的面向对象功能时,很可能会开始将类分离到不同的文件中,从而使代码的组织和管理变得容易得多。 但是,请务必注意,加载许多小JavaScript文件可能会对您的应用程序产生严重的性能影响。 每次Web浏览器需要下载并执行JavaScript文件时,它都必须发出一个单独的HTTP请求,等待服务器响应,然后处理该响应。 因此,加载单个大文件通常比加载许多小文件要快得多。

使用单个大文件的问题在于,它可能是版本控制和代码组织的噩梦,更不用说它可能包含大量的代码,而这些代码实际上并不是应用程序的某些部分所必需的。 解决此问题的方法是在小文件大小之间取得适当的平衡,并最大程度地减少应用程序发出的HTTP请求的数量。

这就是Dojo的构建系统发挥作用的地方。 它使您可以定义层,每个层都结合了多个JavaScript源文件中的源代码,并缩小了生成的单个文件,以将文件大小保持为最小。 缩小过程通过删除所有不必要的空格和注释,并通过将局部变量重命名为较短的名称并在适用的函数中重构它们的用法,从而大幅缩减了代码。 通过使用构建系统,您可以组织源代码以进行开发,但要确保将其部署到生产环境中时可以以最佳性能运行。

使用Dojo构建系统的指南可能需要自己的文章。 幸运的是,Dojo文档具有对该主题的广泛介绍。 有关如何使用构建系统的更多信息,请参阅参考资料 。

结论

在这个由三部分组成的系列文章的第2部分中,该系列文章使用Dojo工具包开发了基于富Web的应用程序,您了解了面向对象的基础知识,JavaScript如何将基于原型的方法用于OOP,以及如何在人们之间长期保持感知。许多传统的关于JavaScript不是强大的OOP支持语言的开发人员是错误的。 然后,您了解了JavaScript的原始面向对象功能,如何定义对象原型以及如何实现继承。 您发现了如何使用Firebug来测试JavaScript代码,而不必将代码保存到文件中。 然后,您学习了如何使用Dojo的dojo.declare函数编写具有Java开发人员更熟悉的样式JavaScript类。 您学习了如何执行继承和多重继承,以及dojo.mixin如何使组合对象的属性变得轻而易举。 您还了解了Dojo的包和模块功能如何使您可以将类分为单独的源文件,就像您对传统的OO语言(如Java语言或C ++)所期望的那样。 最后,您发现Dojo构建系统使您能够以最小化生产环境中的文件大小和HTTP请求的方式,在不影响性能的情况下简化代码组织。

在本系列的第三部分(也是最后一部分)中,您将了解如何使用Dojo的小部件平台Dijit创建交互式的富Internet应用程序。 Dijit建立在Dojo的面向对象功能之上,因此您在本系列的这一部分中学到的知识将在下一部分中证明是有用的。


翻译自: https://www.ibm.com/developerworks/web/library/wa-ground2/index.html

dojo 开发资源

dojo 开发资源_使用Dojo掌握面向对象的开发相关推荐

  1. 手把手教安装java开发环境_手把手教你配置java开发环境-java环境变量设置

    在本篇中将为大家介绍如何在windows下搭建Java的开发环境. 话不多说,直接转入正题.下载java开发工具包JDK 下载地址:http://www.oracle.com/technetwork/ ...

  2. 有哪些网站是django开发的_网站模板建设和定制开发哪个好,有哪些区别?

    网站有哪些作用?很多企业主对于网站建设都没有什么概念,也不知道建设网站有哪些好处,小编告诉大家做好企业的网站不仅可以展示企业的信息,让企业在互联网上有更多的信息推广,而且网站也会在搜索引擎有排名,这样 ...

  3. bs后端开发语言_哪种编程语言适合后端开发?Java和PHP的区别在哪?

    从技术上看在web开发上,Java和PHP哪个更好呢? 一位从多年PHP开发转Java的技术人员说,应是各有千秋,各有各的好处,这是非常实际的答案. java已经是一门很成熟的语言,曾经看到一篇文章, ...

  4. python在web可以开发吗_怎么用python进行web开发

    展开全部 HTML(超文本标记62616964757a686964616fe4b893e5b19e31333363383334语言)是网页的核心,学好HTML是成为Web开发人员的基本条件.HTML很 ...

  5. java web应用开发技术_第一章 Java Web应用开发技术

    Java Web应用开发是基于JavaEE(JavaEnterprise Edition)框架的,而JavaEE是建立在Java平台上的企业级应用解决方案.JavaEES框架提供的Web开发技术主要支 ...

  6. python的运维开发课程_老男孩python高级运维开发课程

    L老男孩培训-python培训二期lesson01(11节) 01-第一天内容介绍及课前思想 02-python介绍及发展 03-python 发展 04-python安装 05-python编程风格 ...

  7. 软件开发面试_如何为成功的软件开发工作面试做准备

    软件开发面试 Job interviews are stressful for many people. Besides the pressure of getting hired, you have ...

  8. chrome 开发工具_我最喜欢的Chrome开发工具提示和技巧

    chrome 开发工具 Chrome Developer Tools are a super powerful suite of tools for developing web applicatio ...

  9. java手机网站开发工具_制作网站常用的网页开发工具有哪些

    我们要想制作好网站其实是离不开网站代码的HTML,我们在制作网站的时候是需要用到一些常用的网页开发工具,才能完成我们网页的编写,那么,你知道制作网站常用的网页开发工具有哪些吗?不清楚的话,下面小编和你 ...

最新文章

  1. Word文档以两列的格式打开,类似于书本那样
  2. [Linux学习]Linux下进程通讯之共享内存
  3. matlab画平行坐标轴的直线
  4. Struts2国际化标签 i18n
  5. PuppeteerSharp: 更友好的 Headless Chrome C# API
  6. oracle ora 00910,NVARCHAR2字段超长问题:ORA-00910: specified length too long for its datatype
  7. 从零开始写一个武侠冒险游戏-8-用GPU提升性能(3)
  8. 多个div在一个div中一行水平显示
  9. linux之awk命令获取最后一列
  10. Linux笔记五 grep文件过滤、find文件/目录查找
  11. 目录-化工工艺设计手册-换热器
  12. scrum敏捷开发与测试
  13. 微信公众号引流的平台有哪些?
  14. 计算机专业比较好的加州州立,美国计算机专业大学排名前十
  15. 分享一个开源免费、功能强大的视频播放器库
  16. 诛仙手游 法宝属性道法性价比
  17. 基于历史使用数据的虚拟机动态整合研究( 文献阅读与问题理解)
  18. 红孩儿编辑器的详细设计第四部分
  19. 带你玩东方外传系列十一 ~ 二十游戏链接
  20. 来来来,做几道「送命题」

热门文章

  1. 华为商城 删除订单_“1111”上能建商城,扶贫惠购火力全开
  2. word 批量取消超链接
  3. oracle 游标非空,oracle 游标判空步骤
  4. CAR (转自MBALIB)
  5. 解决Google中文简体搜索模式无法搜索到敏感内容
  6. 黑马程序员--7K面试题--交通灯管理系统
  7. 2018同城货运行业分析报告
  8. 《利用条件随机场实现中文病历文本中时间关系的自动提取》——阅读笔记
  9. 智慧小屋改进版(Arduino基于开源MQTT接入阿里云IOT)
  10. Netapp磁盘聚合划分