引言
JavaScript 早在发明初期时,仅用来进行简单的表单数据验证,但随着 Web 2.0 技术的蓬勃发展,尤其是近年来 Ajax 的异军突起,JavaScript 如今已成为 Internet 上最流行的脚本语言,用其开发的 web 应用也因高互动性极大的丰富了用户体验。而与此同时,当前的富英特网应用程序的代码量也产生了爆炸式的增长,因此利用面向对象的 JavaScript 编程,构建具有高复用性、易维护、易扩展性、健壮的浏览器端应用,具有重要意义。
与高级语言 Java、C++ 等不同,JavaScript 本身并不是面向对象的语言,没有明确的类的概念,但可以通过核心语言来构建对象系统,模拟类及类的继承。但显然,构建类定义系统并不简单,庆幸的是,dojo.declare 可以帮助我们完成这项复杂的工作。本文将详细讲解如何利用 dojo.declare 定义类,实现单继承及多继承,及其他面向对象特性。为了更深入的理解 dojo.declare 模拟继承的原理,首先介绍原生 JavaScript 两种基本的继承方式,对象冒充及基于原型的继承。
JavaScript 继承方式
关于继承可以朴素的理解为,通过继承,子类可以复用父类的方法,以达到代码重用。JavaScript 可用多种方式模拟继承,本文先举例介绍各种方法,后对比分析优缺点。
对象冒充
在 JavaScript 中,构造函数也和普通的函数一样,可以被赋值和调用,对象冒充通过此原理来模拟继承。
清单 1. 对象冒充示例
Function ClassA(name)
{
this.name = name;
this.sayHello = function(){
alert("Hello, " + this.name);
}
}
Function ClassB(name,time)
{
this.newMethod = ClassA;
this.newMethod(name);
delete this.newMethod;
this.time = time;
this.sayGoodbye = function(){
alert("Goodbye " + this.name + ",it's " + this.time + " now !");
}
}
var objA = new ClassA("Tom");
var objB = new ClassB("Jerry","11:30am");
objA.sayHello(); // output is : "Hello,Tom"
objB.sayHello(); // output is : "Hello,Jerry"
objB.sayGoodbye();// output is : "Goodbye Jerry, it ’ s 11:30am now!"
|
如清单 1 所示,将 ClassA 的构造函数赋值为 ClassB 的一个普通方法,然后调用它,由于此时 this 指向的是 ClassB 的实例,那么 ClassB 的实例就会收到 ClassA 构造函数中定义的属性和方法,从而达到了继承的效果。
需要注意的是,应及时删除临时引用(this.newMethod),以防止 ClassB 更改 ClassA 类对象的引用。因为对临时引用(this.newMethod)的更改,也会导致 ClassA 的结构变化。并且 ClassB 的所有新属性和新方法,应该在删除临时引用后定义,否则,可能会覆盖父类的相关属性和方法。
认识到对象冒充的本质后,可以采用 JavaScript 中的 call 或者 apply 函数达到同样的效果,如清单 2 代码所示。其原理也是在调用 ClassA 的构造函数时,将 this 指向 ClassB 的实例。
清单 2. 利用 call() 实现对象冒充
Function ClassB(name,time)
{
ClassA.call(this,name); // 或者 ClassA.apply(this,[name]);
this.time = time;
this.sayGoodbye = function(){
alert("Goodbye " + this.name + ",it's " + this.time + " now !");
}
}
|
基于原型的继承
JavaScript 中的每个对象都包含一个原型对象(prototype),指向对某个对象的引用,而由于原型对象本身也是对象,则也会包含对它的原型的引用,由此构成一条原型链。原型链终止于内建 Object 类的原型。当要读取某个对象的属性或方法时,JavaScript 首先在该对象中查找,若没有找到,便在该对象的原型中继续查找,若仍未找到,便顺着原型链继续在原型的原型中查找,直到查找到或到达原型链的尽头。这样的系统被称为原型继承。而基于原型的继承,则是指利用了 prototype 或者说以某种方式覆盖了 prototype,从而达到属性及方法复用的目的。如下所示:
清单 3. 原型继承示例
Function ClassA()
{
this.name = "";
this.sayHello = function(){
alert("Hello, " + this.name);
}
}
Function ClassB(){};
ClassB.prototype = new ClassA();
var objB = new ClassB();
objB.name = "Jerry";
objB.sayHello(); //output: "Hello,Jerry";
|
示例代码中将 ClassB 的 prototype 指向 ClassA 的实例,其原型链如图 1 所示,这样 ClassB 便拥有了 ClassA 所有的属性和方法,可以自由的赋值和调用。
图 1. ClassB 原型链
对比
对象冒充和基于原型的方式都可以让子类复用父类的代码以模拟继承,但这两种方法均各有利弊。
利用对象冒充,可以方便的实现多继承,只需要对所有需要继承的父类重复进行赋值流程便可。但这样却有着有明显的性能缺陷,因为在利用对象冒充模拟继承时,每个实例都会拥有一份父类成员变量和方法的副本,而成员方法只是一段对变量操作的可执行文本区域而已,这段区域不用为每个实例复制一份,所有的实例均可共享,这就造成了对内存资源的极度浪费。并且对象冒充也无法继承 prototype 域的变量和方法。
而基于原型的继承则可以使子类拥有一条完整的原型链,并且所有子类实例的原型都指向同一引用,相对于对象冒充,可极大的节省内存开销。但基于原型继承的缺陷也相当明显,就是父类的构造函数不能有参数,因为对子类 prototype 域的修改需在声明子类对象之后才能进行,而用子类构造函数的参数去初始化父类构造函数的属性是无法实现的。
因此可以结合二者的优点,采用混合的方式模拟继承,即用对象冒充的方式给属性赋值,用原型链的方式继承方法,示例代码如下:
清单 4. 混合方式继承示例
Function ClassA(name){
this.name = name;
}
ClassA.prototype.sayHello = function(){
alert("Hello, " + this.name);
}
Function ClassB(name,time){
ClassA.call(this, name);
this.time = time;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayGoodbye = function(){
alert("Goodbye " + this.name + ",it's " + this.time + " now !");
}
var objA = new ClassA("Tom");
var objB = new ClassB("Jerry","11:30am");
objA. sayHello();// output is: "Hello, Tom"
objB.sayHello(); // output is: "Hello, Jerry"
objB.sayGoodbye();//output is: "Goodbye Jerry,it ’ s 11:30am now !"
|
dojo.declare 详解
由上章的介绍可以发现,使用原始的 JavaScript 定义类并实现继承并不是件简单的工作,幸运的是 dojo.declare 提供了一整套的类定义机制,使我们可以像在高级语言中定义类一样,简单明确的完成类的声明。接下来将详细讲解 dojo.delcare 的用法及原理。
运用 dojo.declare 定义类
dojo.declare 方法的 API 如下,它有如下三个参数:
清单 5. dojo.declare 参数定义
dojo.declare(/*String*/ className,
/*Function | Function[]*/ superclass,
/*Object*/ props )
|
- className: 是要要申明的类的类名,也就是创建的构造函数的名称。
- superclass:所要继承的父类,此参数可为 null,表示没有父类,或者为一个父类,或为多个父类的数组,会在后续小节内详述。
- props:散列体,由名、值(key, value)对组成,这个散列体将被添加到定义的类的原型对象中,也即为定义的类被其所有实例共享的属性及方法。其中,key :constructor 为保留字,此函数用来初始化新对象。
如清单 6 所示,我们用 dojo.declare 定义了一个名为 ClassX 的类,父类为空,即无父类,类的每个实例都有属性 messageX,在调用 constructor 函数初始化新对象时赋值,并为类的原型设置了 sayMessageX 方法。
清单 6. dojo.declare 定义类示例
dojo.declare(
"ClassX", // 类的名字
null, // 父类
// 要加入新定义类的原型的所有属性及方法
{
messageX: null,
constructor: function(msgX){
this.messageX = msgX;
},
sayMessageX: function(){
alert("hi, this is " + this. messageX);
}
}
);
|
定义类 ClassX 后,便可以使用了,由示例代码可见,类 ClassX 的对象既是 ClassX 的实例也是 Object 的实例。
清单 7. ClassX 使用示例
var objX = new ClassX("X");
objX. sayMessageX(); //output: "hi, this is X"
objX instanceof ClassX; //true
objX instanceof Object;//true
|
此处以 ClassX 为例,介绍由 dojo.declare 申明的类的原型对象空间,如图 2 所示,主要包括以下属性:
- declaredCalss: 函数名,即传给 dojo.declare 的第一个参数。
- _constructor:类的初始化函数,即 props 中的 constructor 函数,当创建一个新对象时,由 dojo.declare 生成的构造函数自动调用此函数初始化所有的实例属性。
- constructor:由 dojo.declare 为类生成的构造函数。
- inherited:运用此方法可以调用父类的同名函数。
- props 中定义的所有属性及方法,此处包括 messageX 和 sayMessageX。
- 由于 ClassX 没有父类,则其原型的原型指向根原型。
图 2. ClassX 原型对象空间
单继承
假设有一个类 ClassZ,希望继承 ClassX,则可以用 dojo.declare 定义如下:
清单 8. 利用单继承定义 ClassZ 示例
dojo.declare(
"ClassZ", // 类的名字
ClassX, // 父类
// 要加入新定义类的原型的所有属性及方法
{
messageZ: null,
constructor: function(msgX,msgZ){
this.messageZ = msgZ;
},
sayMessageZ: function(){
alert("hi, this is " + this.messageZ);
}
}
)
var objZ = new ClassZ("X","Z");
objZ.sayMessageX();//output is: "hi, this is X"
ojbZ.sayMessageZ();//output is: "hi, this is Z"
|
如代码所示,为了继承父类,仅需将父类作为 dojo.declare 的第二个参数就可以了。但其实 dojo.declare 帮我们做了以下两个工作:
- 构造新类的原型对象,并将其原型指向父类的原型。
- dojo.delcalre 为 ClassZ 生成的构造函数,将会先调用父类的构造函数,再调用子类的构造函数,这点与高级语言在继承中调用构造函数的顺序一致。如创建 ClassZ 对象,需执行类似以下的代码,这非常类似于上一章节中提到的混合继承方式。
清单 9. 创建 ClassZ 实际执行代码 ( 单继承 )
Var objZ = new ClassZ("X","Z");
ClassX.apply(this,["X","Z"]);
ClassZ._constructor.apply(this, ["X","Z"]);
|
ClassZ 的原型对象空间如下图所示,可以看到 ClassZ 类的原型引用了 ClassX 类的原型对象,则当如清单 8 中调用 ClassX 的方法时,首先将在 ClassZ 类的原型空间查找,在未查找到后,继而在 ClassX 的原型查找,查找到后调用。
图 3. ClassZ 原型对象空间 ( 单继承 )
多继承
假设有 ClassY 定义如下:
清单 10. ClassY 示例
dojo.declare(
"ClassY", // 类的名字
null, // 父类
{
messageY: null,
constructor: function(msgY){
this.messageY = msgY;
},
setMessageY: function(msgY){
this.messageY = msgY;
},
sayMessageY: function(){
alert("hi, this is " + this.messageY);
}
}
);
|
而 ClassZ 希望同时继承自 ClassX 及 ClassY,则可由 dojo.declare 定义如下:
清单 11. 利用多继承定义 ClassZ 示例
dojo.declare(
"ClassZ", // 类的名字
[ClassX,ClassY] // 父类
// 要加入新定义类的原型的所有属性及方法
{
messageZ: null,
constructor: function(msgX,msgY,msgZ){
this.messageZ = msgZ;
this.setMessageY(msgY);
},
sayMessageZ: function(){
alert("hi, this is " + this.messageZ);
}
}
);
|
虽然我们仅将需继承的父类放入数组传递给 dojo.declare, 但这样定义出的类 ClassZ 却拥有 ClassX 与 ClassY 的全部功能。此处关于 ClassZ 初始化函数的详细讲解见下节。需注意的是,当将数组作为 superclass 参数时,仅第一个元素为新类的父类,之后的类会被当做为聚合类。聚合类中的属性和方法会被拷贝到新类中,以使新类具有聚合类的功能,从而达到模拟继承的效果。对于这种拷贝,除非属性保存的是数字,字符串,布尔,或者 null,否则均为引用拷贝。
下图为 ClassZ 的原型对象空间,由图可见,ClassZ 原型链的上一级指向的是 ClassX 的原型,则说明 ClassX 为其父类,而其原型中包含的 setMessageY 和 sayMessageY 函数则指向与 ClassY 原型对象中相同函数对象。
图 4. ClassZ 原型对象空间 ( 多继承 )
由于 dojo.declare 是用聚合类来模拟多继承,则 ClassZ 的实例是 ClassZ ,ClassX 类以及 Object 类的实例,但不会是 ClassY 类的实例,如下代码所示:
清单 12. ClassZ 使用示例
var objZ = new ClassZ("X","Y","Z");
objZ.sayMessageZ();//output is : "hi, this is Z"
var check;
check = objZ instanceof ClassZ; // true
check = objZ instanceof ClassX; // true
check = objZ instanceof Object; // true
check = objZ instanceof ClassY; // false
|
预处理构造函数参数
对于继承和聚合,若子类,父类或聚合类之间的构造函数签名不同,则需要预处理构造函数的参数。
例如,ClassX(清单 6),ClassY(清单 10)及 ClassZ(清单 11) 的构造函数签名分别为:(msgX), (msgY), (msgX,msgY,msgZ) ; 当我们创建 ClassZ 的实例时,在默认情况下,dojo.declare 会按序先将参数传递给父类的构造函数,然后传递给聚合类的构造函数,最后传递给子类的初始化函数,如以下代码所示:
清单 13. 创建 ClassZ 实际执行代码 ( 多继承 )
var objZ = new ClassZ("X","Y","Z");
ClassX.apply(this,["X","Y","Z"]);
ClassY.apply(this, ["X","Y","Z"]);
ClassZ.prototype._constructor.apply(this, ["X","Y","Z"]);
|
由于 ClassX 仅需一个参数,因此可以忽略掉后两个参数“Y”,“Z”,被正确的初始化。而 ClassY 虽然也仅需一个参数,但传递给它的第一个参数却是“X”,因此它会将“X”当做“Y”,而被错误的初始化。为纠正这个错误,我们在 ClassZ 的构造函数中显示的调用了 setMessageY (msgY) 这个方法。 ClassZ 的初始化函数也可正确的接收这三个参数,它首先正确的初始化了 msgZ,后初始化 ClassY 类的实例变量。但由于父类及聚合类的构造函数会先于子类的初始化函数调用,则在 ClassZ 的初始化函数调用 setMessageY(msgY) 之前,属性 msgY 都被初始化错误。
大多数情况下,都可运用这种方法修复错误的初始化,但不正确的初始化有可能会带来一些坏的副作用,如抛出异常。
将散列表作为构造函数的参数则是一种更简单安全的做法。如,通过以下方式创建 ClassZ 的实例(清单 13 中第一行),需将本文中 ClassX,ClassY,ClassZ 的初始化函数重写如下:
清单 14. 初始化函数示例
var ClassZ = new ClassZ({msgX:"X",msgY:"Y",msgZ:"Z"});
// ClassX
constructor: function(args){
if(args && args.msgX)
this.msgX = args.msgX;
}
// ClassY
constructor: function(args){
if(args && args.msgY)
this.msgY = args.msgY;
}
// ClassZ
constructor: function(args){
if(args && args.msgZ)
this.msgZ = args.msgZ;
}
|
则通过此方式创建 ClassZ 的实例的过程中,不会有任何的初始化错误出现,并且此种方式也消除了对参数顺序的依赖。当参数个数过多时,将会是个不错的选择。
结束语
本文详细讲解了 dojo.declare 的各种用法,并通过实例及图解深入分析了其通过原型链及聚合类模拟面向对象的继承的原理。dojo.declare 不仅给 JavaScript 开发人员提供了一种自然的方式简洁明了的创建类,而且可通过已定义的类来组合新类,使人们可以更简单高效的复用代码。相信通过 dojo.declare,可以使您开发出更易扩展、易维护、更健壮的 web 应用程序!
分享到:
相关推荐
### ArcGIS Server JavaScript API 访问天地图代码详解 #### 一、背景介绍 随着地理信息系统(GIS)技术的发展,地图服务在各个领域的应用越来越广泛。ArcGIS Server 是一款强大的地理信息系统服务器产品,它提供了...
**ArcGIS JavaScript API 1.2 知识详解** ArcGIS JavaScript API 是Esri公司推出的一款用于构建地理信息系统(GIS)应用的JavaScript库,它允许开发者在网页端创建丰富的地图和地理分析功能。1.2版本是这个API的一...
**DOJO 框架详解** DOJO 是一个开源的 JavaScript 库,它提供了一整套功能丰富的工具,用于构建富交互式的 Web 应用程序。这个“DOJO-DEMO 官网提取版”是基于 DOJO 官方网站在 2013 年 1月的演示示例集合,对于...
区块链_智能合约_Solidity_保险应用_基于以太坊的技_1744433266
内容概要:本文档详细介绍了在Windows系统上安装MySQL数据库的具体步骤。首先,需要配置系统环境变量,包括新建MYSQL_HOME变量并将其添加到PATH中;其次,创建并编辑my.ini配置文件,设置MySQL的基本参数如端口、字符集、数据存放目录等;接着,在命令行工具中通过一系列指令完成MySQL的初始化、服务安装、启动以及root用户的密码设置和权限调整。整个流程涵盖了从环境搭建到最终确保MySQL服务正常运行的所有关键环节。 适合人群:适用于有一定计算机操作基础,尤其是对数据库管理有一定兴趣或需求的技术人员。 使用场景及目标:①帮助用户在本地机器上成功部署MySQL数据库环境;②确保用户能够掌握MySQL的基本配置与管理技能,如环境变量配置、服务安装与卸载、用户权限管理等。 其他说明:在安装过程中可能会遇到一些常见问题,例如由于之前版本残留导致的服务安装失败,此时可以通过命令行删除旧服务(sc delete mysql)来解决。此外,为了保证安全性,务必及时修改root用户的初始密码。
内容概要:`STARTUP.A51` 是 Keil C51 编译器自带的启动文件,用于初始化 8051 单片机的硬件和软件环境。该文件主要完成三个任务:初始化堆栈指针、清零内部数据存储器、跳转到主程序。文件中定义了内存模式(如 SMALL),并设置了堆栈指针的初始值为 0x60。接着通过循环将内部数据存储器的所有字节清零,确保程序开始时数据存储器的状态是确定的。此外,文件还列出了 8051 单片机的各个中断向量地址,并为每个中断提供占位符,实际的中断处理程序需要在其他文件中实现。最后,启动代码段初始化堆栈指针和数据段后,跳转到 `MAIN` 函数开始执行主程序。; 适合人群:对嵌入式系统开发有一定了解,尤其是使用 8051 单片机的开发者。; 使用场景及目标:①理解 8051 单片机启动文件的工作原理;②掌握如何初始化堆栈指针和数据段;③熟悉中断向量表的设置及其作用。; 其他说明:此文件为程序正常运行提供了必要的初始化操作,开发者可以根据具体需求修改该文件以适应不同的硬件和软件环境。
内容概要:该论文研究了一种基于行波理论的输电线路故障诊断方法。当输电线路发生故障时,故障点会产生向两侧传播的电流和电压行波。通过相模变换对三相电流行波解耦,利用解耦后独立模量间的关系确定故障类型和相别,再采用小波变换模极大值法标定行波波头,从而计算故障点距离。仿真结果表明,该方法能准确识别故障类型和相别,并对故障点定位具有高精度。研究使用MATLAB进行仿真验证,为输电线路故障诊断提供了有效解决方案。文中详细介绍了三相电流信号生成、相模变换(Clarke变换)、小波变换波头检测、故障诊断主流程以及结果可视化等步骤,并通过多个实例验证了方法的有效性和准确性。 适合人群:具备一定电力系统基础知识和编程能力的专业人士,特别是从事电力系统保护与控制领域的工程师和技术人员。 使用场景及目标:①适用于电力系统的故障检测与诊断;②能够快速准确地识别输电线路的故障类型、相别及故障点位置;③为电力系统的安全稳定运行提供技术支持,减少停电时间和损失。 其他说明:该方法不仅在理论上进行了深入探讨,还提供了完整的Python代码实现,便于读者理解和实践。此外,文中还讨论了行波理论的核心公式、三相线路行波解耦、行波测距实现等关键技术点,并针对工程应用给出了注意事项,如波速校准、采样率要求、噪声处理等。这使得该方法不仅具有学术价值,也具有很强的实际应用前景。
内容概要:本文详细介绍了光伏-混合储能微电网能量管理系统的模型架构及其控制策略。首先探讨了光伏发电模块中的MPPT(最大功率点跟踪)控制,采用扰动观察法和改进型变步长策略来提高光伏板的发电效率。接着重点讲解了混合储能系统的功率分配,利用一阶低通滤波算法将功率需求分为低频和高频两部分,分别由蓄电池和超级电容处理。此外,文中还深入讨论了SOC(荷电状态)管理策略,确保电池和超级电容在不同工作状态下保持最佳性能。仿真结果显示,在光伏出力剧烈波动的情况下,系统能够有效地维持稳定的电压水平,并显著提高了储能设备的使用寿命。 适合人群:对光伏微电网、储能技术和能量管理系统感兴趣的科研人员、工程师和技术爱好者。 使用场景及目标:适用于研究和开发高效、可靠的光伏-混合储能微电网系统,旨在优化能量管理和提高系统稳定性。具体应用场景包括但不限于家庭光伏系统、小型微电网以及工业能源管理系统。 其他说明:文中提供了详细的代码实现和仿真结果,便于读者理解和复现实验。同时,模型设计采用了模块化思路,方便进行个性化修改和扩展。
内容概要:本文详细介绍了基于MATLAB和CVX平台实现的储能调峰调频联合优化模型。该模型不仅涵盖了储能的基本参数设定、负荷不确定性处理、充放电策略制定,还包括了调峰调频的联合调度、功率约束处理、鲁棒优化等方面的内容。通过构建考虑电池退化成本、充放电功率约束以及用户负荷不确定性的储能优化模型,展现了储能系统在电力系统中的高效协同工作。文中提供了详细的代码示例,解释了各个部分的功能和实现方法,强调了模型的深度与创新性。 适合人群:适用于具有一定编程基础和技术背景的研究人员、工程师以及希望深入了解储能系统优化的学生。 使用场景及目标:该模型主要用于电力系统中储能设备的优化调度,旨在提高储能系统的经济效益和社会效益。通过联合调峰调频,能够显著提升储能系统的收益,实现1+1>2的超线性增益效果。此外,该模型还可以用于教学和科研,帮助初学者理解和掌握储能优化的相关技术和理论。 其他说明:代码中包含了丰富的注释和模块化的子程序,使得整个模型易于理解和扩展。对于有经验的开发者,可以在现有基础上进一步改进和定制,以适应不同的应用场景。
大模型技术白皮书2023版
图像增广 PyTorch 版
批量修改文件名可以帮助用户节省大量时间,提高工作效率 里面附带使用教程
《计算机应用基础》第2章--Windows-XP操作系统.ppt
包括:源程序工程文件、Proteus仿真工程文件、电路原理图文件、配套技术手册、论文资料等 1、采用51/52单片机(通用)作为主控芯片; 2、采用1602液晶显示使用过程及状态,液晶屏亮度会随光线自动调整; 3、按键输入6位密码,输入密码正确则锁打开,显示open!输入密码错误次数超过3次,蜂鸣器报警并且锁定键盘; 4、密码可以自己修改,必须是锁打开时才能改密,为防止误操作,修改密码得输入两次; 5、采用24C02保存密码,掉电不丢失; 6、可通过红外遥控器输入密码操作锁的状态;
内容概要:本文深入剖析了2025年全球感知技术的十大发展趋势,涵盖多模态感知融合、3D感知与空间计算、脑机接口中的感知反馈技术、5G/6G赋能的超低延迟感知、语音与情感识别的高级化、生物感知与数字健康、环境感知与自适应智能、增强现实(AR)与触觉反馈技术、气味与化学感知、量子感知与极端条件测量。文章详细介绍了每项技术的技术原理、关键算法、实现方式、商业案例及未来前景,强调了感知技术在智慧城市、自动驾驶、智慧医疗、工业自动化等领域的深刻影响。报告指出,感知技术正从单一传感模式向多模态融合、从二维数据向三维空间重建、从传统网络通信向超低延迟和高可靠性网络升级,实现全场景、全维度的智能感知。; 适合人群:对感知技术感兴趣的科技爱好者、研究人员、决策者、企业管理层和投资人。; 使用场景及目标:①了解感知技术的最新进展和未来发展方向;②为技术研究提供全面、深入的参考;③为商业应用提供具体的案例和前景分析;④推动跨领域协同创新,构建开放共赢的产业生态。; 其他说明:报告基于近年来技术研发的最新进展、业界前沿的技术路线以及各大科技企业在商业落地方面的丰富实践。随着感知技术的不断成熟,数据隐私与安全保护问题也需高度重视,以确保技术进步与社会伦理和谐统一。未来,感知技术将成为推动社会进步和产业升级的重要力量,为实现万物互联、智慧决策和智能体验提供无限可能。
本论文主要论述了如何使用JAVA语言开发一个校园新闻网站 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述校园新闻网站的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统进行各个阶段分析设计。 校园新闻网站的主要使用者分为管理员和用户,实现功能包括管理员:首页、个人中心、用户管理、新闻类型管理、校园新闻管理、留言板管理、论坛交流、系统管理,用户前台:首页、校园新闻、论坛交流、留言反馈、个人中心、后台管理等功能。由于本网站的功能模块设计比较全面,所以使得整个校园新闻网站信息管理的过程得以实现。 本系统的使用可以实现本校园新闻网站管理的信息化,可以方便管理员进行更加方便快捷的管理,可以提高管理人员的工作效率。 基于Springboot+vue的校园新闻网站【源码+数据库+参考论文】 感兴趣自行下载学习!
内容概要:本文详细探讨了三相三电平PWM整流器的闭环控制策略及其核心技术——三电平SVPWM算法。文章首先介绍了三相三电平PWM整流器的基本概念和优势,如输出三种电平以降低谐波含量并减少滤波器体积和成本。接着阐述了闭环控制策略的重要性,强调了电压外环和电流内环的双闭环控制机制。随后,文章深入讲解了三电平SVPWM算法的工作原理,包括空间电压矢量的选择、扇区判断、矢量作用时间和死区补偿等关键技术环节。此外,还讨论了中点电位平衡的问题以及PI参数的整定方法。最后,通过示波器测试验证了系统的性能指标,如THD低于3%,直流电压纹波小于1%。 适合人群:从事电力电子领域的工程师和技术人员,尤其是对三相三电平PWM整流器及其控制策略感兴趣的读者。 使用场景及目标:适用于高压大功率场合,旨在提高整流器的性能,降低谐波含量,实现单位功率因数运行。通过合理设计闭环控制策略和优化SVPWM算法,确保整流器在各种工况下都能稳定、高效地工作。 其他说明:文中提供了大量MATLAB和C语言代码片段,帮助读者更好地理解和实现相关算法。同时,针对实际调试过程中遇到的问题给出了实用的解决方案,如中点电位平衡和死区补偿等。
全新红娘本地交友系统定制版源码 相亲婚恋交友小程序源码
内容概要:文章探讨了AI技术,特别是DeepSeek,如何驱动地图生成的变革。首先介绍了地图制图在AI时代的背景与挑战,强调了DeepSeek与地图融合的两种主要方式:嵌入地图制图链和研发地图语言自身的预训练模型。随后详细描述了DeepSeek在地图生成中的具体应用,包括智能化地图生成器DoMapAI的整体框架,地图制图链中的知识图谱推理路径,以及地图语言的Token化过程。最后,文章总结了AI时代地图制图的职业变化和技术变革,指出地图制图正经历“大变局”。 适合人群:从事地图制图及相关领域的研究人员、工程师,以及对AI与地图生成感兴趣的学者。 使用场景及目标:①理解AI技术在地图生成中的应用,特别是DeepSeek的作用;②掌握智能化地图生成器DoMapAI的工作原理及其应用场景;③学习地图语言Token化的方法及其在地图生成中的应用;④探索AI时代地图制图的职业发展方向和技术变革。 阅读建议:本文内容较为专业,建议读者先了解基本的AI技术和地图制图知识。重点关注DeepSeek与地图融合的具体方法和应用场景,理解智能化地图生成器DoMapAI的工作流程,以及地图语言Token化的实现过程。在阅读过程中,可以结合实际案例进行思考,以更好地理解AI技术对地图制图的影响。
chromedriver-mac-arm64-135.0.7049.114.zip