- 浏览: 1683745 次
- 性别:
-
文章分类
- 全部博客 (2929)
- 非技术 (18)
- Eclipse (11)
- JAVA (31)
- 正则表达式 (0)
- J2EE (4)
- DOS命令 (2)
- WEB前端 (52)
- JavaScript (69)
- 数据库 (8)
- 设计模式 (0)
- JFreechart (1)
- 操作系统 (1)
- 互联网 (10)
- EasyMock (1)
- jQuery (5)
- Struts2 (12)
- Spring (24)
- 浏览器 (16)
- OGNL (1)
- WebService (12)
- OSGi (14)
- 软件 (10)
- Tomcat (2)
- Ext (3)
- SiteMesh (2)
- 开源软件 (2)
- Hibernate (2)
- Quartz (6)
- iBatis (2)
最新评论
解开JavaScript生命的达芬奇密码
——如何使用JavaScript进行可靠的继承调用
作者:cleverpig
提出问题:
几
乎每位在开发JavaScript时尝试应用面向对象技术的开发者,或多或少都会问自己一个问题:“如何调用父类(super
class)的方法?”在Ajax技术还没有目前这样炙手可热之前,这种问题很少出现,因为大多数开发者仅在进行客户端form验证或者简单的
DHTML/DOM操作时使用JavaScript。在那些简单的解决方案中,函数式编程(functional programming)
是
很有意义的,面向对象编程则处在次之重要的位置。现在,Ajax技术发展势头迅猛,开发者已经建立了一个调用大量客户端JavaScript、不断增长
的、复杂的系统。因此,在JavaScript上尝试OO技术便成为了管理复杂性的一种手段。在此过程中,多数开发者很快便认识到:JavaScript
是一种原型化的(prototypical)语言,它缺少OO自身带来的多种便利。
OO设计的主旨和关于它的一些话题谈
起来很大,但只着眼于Class的定义方式,我认为它是JavaScript开发者尝试解决问题的首选。因此,你可以在互联网上找到许多不同的问题解决案
例,但在我看过它们后不免有些失望——这些案例都是在某个场合下适用,而不是放之四海而皆准的通法。而我对这个话题的兴趣来自于我的team在开发ThinWire Ajax Framework
的影响。由于这个框架生成出对客户端代码的需求,才使我们“被迫”去实现可靠的、支持父类方法调用的OO模式。通过父类调用,你可以进一步依靠类的继承特性来核心化通用代码,从而更易于减少重复代码,去掉客户端代码的坏味道
。
下面罗列出了一些在我的研究过程中遇到的解决方式。最终,我没有从中找出一个可以接收的解决方案,于是我不得不实现一个自己的解决方案,你将在本文的结尾部分看到这个方案。
然而父类调用在这里是最重要的OO机制,因此我需要一个相应的工作模式,也正是因为在我的观点中原型化方式是丑陋的,所以我更需要一种更加自然地使用JavaScript定义类的方法。
More Solutions:
好吧,让我们进入讨论。正如开发者所察觉的那样,在JS中实现基本的继承是很容易的事,事实上有一些众所周知的方法:
丑陋的Solution:
没有进行父类调用的简单继承:
// 提前写好的JavaScript Class定义和继承 // 当然,这种代码很丑陋,散发着代码的坏味道。 function BaseClass() { //BaseClass constructor code goes here } BaseClass.prototype.getName = function() { return "BaseClass"; } function SubClass() { //SubClass constructor code goes here } //Inherit the methods of BaseClass SubClass.prototype = new BaseClass(); //Override the parent's getName method SubClass.prototype.getName = function() { return "SubClass"; } //Alerts "SubClass" alert(new SubClass().getName());
导致IE内存泄露
的Solution:
这种实现方式能够导致在IE中的内存泄漏,你应该尽量避免:
// 运行时的JavaScript Class 定义和继承 // 看上去很传统,但这些脚本会导致在Internet Explorer中的内存泄漏. function BaseClass() { this.getName = function() { return "BaseClass"; }; //BaseClass constructor code goes here } function SubClass() { //在对象实例建立时重载父类的getName方法 this.getName = function() { return "SubClass"; } //SubClass constructor code goes here } //Inherit the methods of BaseClass SubClass.prototype = new BaseClass(); //Alerts "SubClass" alert(new SubClass().getName());
就像我在第一个实现方法中所注释的那样,第一个实现方法有些丑陋,但它相比引起内存泄漏的第二种方式便是首选了。
我把这两种方法放在这里的目的是指出你不应该使用它们。
硬性编码的Solution:
让我们看一下第一个例子,它采用了标准的原型化方式,但问题是:它的子类方法如何调用父类(基类)方法?下面是一些开发者尝试并采用的方式:
一种企图进行父类调用的“通病”:
function BaseClass() { } BaseClass.prototype.getName = function() { return "BaseClass(" + this.getId() + ")"; } BaseClass.prototype.getId = function() { return 1; } function SubClass() {} SubClass.prototype = new BaseClass(); SubClass.prototype.getName = function() { //调用父类的getName()方法 //哈哈,这是对父类调用的直接引用吗? return "SubClass(" + this.getId() + ") extends " + BaseClass.prototype.getName(); } SubClass.prototype.getId = function() { return 2; } //输出结果:"SubClass(2) extends BaseClass(1)"; //这是正确的输出吗? alert(new SubClass().getName());
上
面的代码是对第一段脚步进行修改后的版本,我去掉了一些注释和空格,使你能注意到新的getId()方法和对父类的调用。你一定急于知道通过这样对
BaseClass的硬性编码引用(hard coded reference),它是否能进行正确地调用BaseClass的方法?
一
个正确的、多态的父类调用必做的事情是保证“this”引用指向当前对象实例和类方法。在这里,看上去和它应该输出的结果非常接近,看上去好像在
SubClass中调用了BaseClass的getName()方法。你发现问题了吗?这个问题是非常细小的,但却很重要决不能忽视。通过使用上面的父
类调用语法,BaseClass的getName()方法被调用,它返回一个字符串:包括类名和“this.getId()”的返回值。问题在于
“this.getId()”应该返回2,而不是1。如果这和你所想的不同,你可以查看Java或者C#这类OO语言的多态性。
改进后的硬性编码Solution:
你可以通过一个微小的改动来解决这个问题。
静态(硬编码)父类调用:
function BaseClass() { } BaseClass.prototype.getName = function() { return "BaseClass(" + this.getId() + ")"; } BaseClass.prototype.getId = function() { return 1; } function SubClass() {} SubClass.prototype = new BaseClass(); SubClass.prototype.getName = function() { //一点魔法加上多态性! //但很明显,这还是一个直接引用! return "SubClass(" + this.getId() + ") extends " + BaseClass.prototype.getName.call(this); } SubClass.prototype.getId = function() { return 2; } //输出结果:"SubClass(2) extends BaseClass(2)"; //Hey, 我们得到了正确的输出! alert(new SubClass().getName());
在ECMA-262 JavaScript/EcmaScript标准
中,Call()
方法是所有Function实例的一个成员方法,这已经被所有的主流浏览器所支持。JavaScript把所有的function看作对象,因此每个
function都具有方法和附着其上的属性。Call()方法允许你调用某个function,并在function的调用过程中确定“this”变量
应该是什么。JavaScript的function没有被紧紧地绑定到它所在的对象上,所以如果你没有显式地使用call()方法,“this”变量将
成为function所在的对象。
另外一种方法是使用apply方法,它和call()方法类似,只在参数上存在不同:apply()方法接受参数的数组,而call()方法接受单个参数。
Douglas Crockford
的Solution:
现在回溯到上面的示例,在这个示例中唯一的问题就是父类引用是直接的、硬性编写的。它可以适用于小型的类继承环境,但对于具有较深层次的大型继承来讲,这些直接引用非常难于维护。
那么,有解决方法吗?不幸的是这里没有简单的解决方案。
JavaScript没有提供对通过“隐性引用”方式调用父类方法的支持,这里也没有在其它OO语言中使用的“super”变量的等价物。于是,一些开发者做出了自己的解决方案,但就像我前面提到的那样,每个解决方案都存在某种缺点。
例如,下面列出的众多著名方法之一:JavaScript大师[ur=http://en.wikipedia.org/wiki/Douglas_Crockford]Douglas Crockford[/url]
在他的《Classical Inheritance in JavaScript》
中提出的方法。
Douglas Crockford的方法在多数情况下可以正常工作:
一次性支持代码:
//Crockford的方法:给所有的function都增加'inherits' 方法、 //每个类都增加了'uber'方法来调用父类方法 Function.prototype.inherits = function(parent) { var d = 0, p = (this.prototype = new parent()); this.prototype.uber = function(name) { var f, r, t = d, v = parent.prototype; if (t) { while (t) { v = v.constructor.prototype; t -= 1; } f = v[name]; } else { f = p[name]; if (f == this[name]) { f = v[name]; } } d += 1; r = f.apply(this, Array.prototype.slice.apply(arguments, [1])); d -= 1; return r; }; };
运行示例:
function BaseClass() { } BaseClass.prototype.getName = function() { return "BaseClass(" + this.getId() + ")"; } BaseClass.prototype.getId = function() { return 1; } function SubClass() {} SubClass.inherits(BaseClass); SubClass.prototype.getName = function() { //这里看上去非常的清晰,它调用了BaseClass的getName()方法 return "SubClass(" + this.getId() + ") extends " + this.uber("getName"); } SubClass.prototype.getId = function() { return 2; } function TopClass() {} TopClass.inherits(SubClass); TopClass.prototype.getName = function() { //这里看上去非常的清晰,它调用了SubClass的getName()方法 return "TopClass(" + this.getId() + ") extends " + this.uber("getName"); } TopClass.prototype.getId = function() { //Ok, 因此this.getId()应该总是 //返回调用SubClass的getId()方法的返回值(2)。 return this.uber("getId"); } //输出结果:"TopClass(2) extends SubClass(1) extends BaseClass(1)" //嗯?后面的两次this.getId()调用都没有返回2. //发生了什么? alert(new TopClass().getName());
上
面代码的第一部分包括了Crockford的“inherit”和“uber”方法代码。第二部分看上去和前面的示例很类似,除了我添加了用来演示
Crockford方式所存在问题的第三层继承关系。诚然,Crockford这位JavaScript大师的方法是我所找到的最可靠的方法之一,我很敬
佩他在JavaScript编程方面做出的贡献。但是,如果你使用三个依次继承的类来考核他的代码,你将从输出中发现这里存在着细微的问题。
从
输出结果看,第一次调用的this.getId()返回了TopClass当前的id值“2”,但在调用SubClass和BaseClass的
getName()方法时返回了“1”而不是“2”。从代码上看,
在getName()方法中的父类调用行为是正确的,三个类的名字都被正确地显示出来。唯一的问题出现在this.uber("getId")这个父类调
用被放入调用堆栈(call
stack)时。因为此时当前对象是一个TopClass实例,而每次调用在调用堆栈中的this.getId()都应该返回调用TopClass的
getId()方法后的返回值。
而问题是TopClass的this.getId()方法通过
this.uber("getId")执行了父类调用,这三次this.getId()调用中的后两次错误地调用了BaseClass的getId()方
法,这样便在输出结果中显示了两次“1”。正确的行为应该是调用三次SubClass的getId()方法,在输出结果中显示三次“2”。大家可以通过FireFox的FireBug插件
进行代码debug进行观察。
这是十分难以描述的现象,我不能保证我能把它解释清楚。但是至少从上面的运行结果中可以看出它是错误的。
另外,Crockford的方法和其它一些方法的劣势在于每个父类调用都需要一个额外的方法调用和额外的某种处理。这是否成为你所面临的问题,取决于你所使用的父类调用深度。在ThinWire
项目的客户端代码中使用了大量的父类调用,因此父类调用的可靠性和快速性在项目中是很重要的。
我的初级Solution:
面对这样的窘境——Crockford的方法出现问题、在互联网上没有找到符合要求的方法,我决定看看我自己是否可以发明一种可以满足要求的方法。
这花掉了我近一周的时间来使代码工作并满足各种情况,但我对它的工作情况很有信心,并且很快把它与framework集成在一起,TinWire的beta和beta2两个版本中都使用了这些“初级设计”的代码。
动态父类调用:
一次性支持代码:
//定义最顶级类 function Class() { } Class.prototype.construct = function() {}; Class.__asMethod__ = function(func, superClass) { return function() { var currentSuperClass = this.$; this.$ = superClass; var ret = func.apply(this, arguments); this.$ = currentSuperClass; return ret; }; }; Class.extend = function(def) { var classDef = function() { if (arguments[0] !== Class) { this.construct.apply(this, arguments); } }; var proto = new this(Class); var superClass = this.prototype; for (var n in def) { var item = def[n]; if (item instanceof Function) { item = Class.__asMethod__(item, superClass); } proto[n] = item; } proto.$ = superClass; classDef.prototype = proto; //赋给这个新的子类同样的静态extend方法 classDef.extend = this.extend; return classDef; };
运行示例:
//Hey, 注意一下这个类的定义方式 //看上去比其它方式要清楚些 var BaseClass = Class.extend({ construct: function() { /* optional constructor method */ }, getName: function() { return "BaseClass(" + this.getId() + ")"; }, getId: function() { return 1; } }); var SubClass = BaseClass.extend({ getName: function() { //调用BaseClass的getName()方法 return "SubClass(" + this.getId() + ") extends " + this.$.getName.call(this); }, getId: function() { return 2; } }); var TopClass = SubClass.extend({ getName: function() { //调用SubClass的getName()方法 return "TopClass(" + this.getId() + ") extends " + this.$.getName.call(this); }, getId: function() { //this.getId()总是返回调用父类的getId()方法的返回值(2) return this.$.getId.call(this); } }); //输出结果:"TopClass(2) extends SubClass(2) extends BaseClass(2)" //一切都正确! alert(new TopClass().getName());
这
里是前面示例的,但是目前这种方式包括了通过“extend”方法实现的十分清晰的类定义模式和正确的父类调用语义。尤其是“extend”方法通过一个
中间function封装了类定义中的每个方法,这个中间function在每次方法调用时首先把当前父类引用“$”
与正确的父类引用相互交换,然后把这个正确的父类引用传递给apply()进行方法调用,最后再将把当前父类引用“$”
与正确的父类引用交换回来。这种方式唯一的问题就是它需要一些中间function,它们会对性能产生不良影响。所以近来我重新审视了设计、完成了去掉了
中间function了一种改良的方式。
改良后的Solution:
动态父类调用快速版本:
一次性支持代码
//定义最顶级类 function Class() { } Class.prototype.construct = function() {}; Class.extend = function(def) { var classDef = function() { if (arguments[0] !== Class) { this.construct.apply(this, arguments); } }; var proto = new this(Class); var superClass = this.prototype; for (var n in def) { var item = def[n]; if (item instanceof Function) item.$ = superClass; proto[n] = item; } classDef.prototype = proto; //赋给这个新的子类同样的静态extend方法 classDef.extend = this.extend; return classDef; };
运行示例:
//Hey, 注意一下这个类的定义方式 //看上去比其它方式要清楚些 var BaseClass = Class.extend({ construct: function() { /* optional constructor method */ }, getName: function() { return "BaseClass(" + this.getId() + ")"; }, getId: function() { return 1; } }); var SubClass = BaseClass.extend({ getName: function() { //调用BaseClass的getName()方法 return "SubClass(" + this.getId() + ") extends " + arguments.callee.$.getName.call(this); }, getId: function() { return 2; } }); var TopClass = SubClass.extend({ getName: function() { //调用SubClass的getName()方法 return "TopClass(" + this.getId() + ") extends " + arguments.callee.$.getName.call(this); }, getId: function() { // this.getId()总是返回调用父类的getId()方法的返回值(2) return arguments.callee.$.getId.call(this); } }); //输出结果:"TopClass(2) extends SubClass(2) extends BaseClass(2)" //工作正常!而且没有任何中间function alert(new TopClass().getName());
这是最后的设计,它使用了JavaScript中一点鲜为人知的特性:callee。
在
任何方法执行过程中,你可以查看那些通过“arguments”数组传入的参数,这是众所周知的,但很少有人知道“arguments”数组包含一个名为
“callee”的属性,它作为一个引用指向了当前正在被执行的function,而后通过“$”便可以方便的获得当前被执行function所在类的父
类。这是非常重要的,因为它是获得此引用的唯一途径(通过“this”对象获得的function引用总是指向被子类重载的function,而后者并非
全是正在被执行的function)。
原文作者附言:
Ok,这便是相对彻底的问题解决方案了。但是我想通过把它的细节写成文档让每个人阅读,以致我可以从中找出漏洞不断地完善代码。欢迎对我的文章进行评论和建议!
--Joshua Gertzen
参考资源:
ThinWire RIA Ajax GUI Framework
原文作者Joshua Gertzen的《Object Oriented Super Class Method Calling with JavaScript》
Douglas Crockford 的《Classical Inheritance in JavaScript》
Kevin Lindsey的《JavaScript Tutorial》
Tom Wright的《Super Simulation in JavaScript OOP》
Mozilla's Core JavaScript 1.5 手册
Jesse James Garrett的《Ajax: A New Approach to Web Applications》
Microsoft's HTML & DHTML 手册
W3C Document Object Model (DOM) 规范
ECMA-262 EcmaScript (JavaScript / JScript) 规范
感谢阅读此文
发表评论
-
Javascript评估用户输入密码的强度的方法 代码
2009-07-28 17:50 719用Javascript评估用户输入密码的强度密码已经是我们生活 ... -
图片和文字放一起,不能居中的解决方法
2009-07-29 14:47 965<td align="center" ... -
掌控上传进度的AJAX Upload(转贴)
2009-08-05 17:59 732掌控上传进度的AJAX Uploa ... -
Javascript跨域访问解决方案
2009-08-11 20:11 639由于安全方面的考虑,Javascript被限制了跨域访问的能力 ... -
不唐突的JavaScript的七条准则(转载)
2009-08-12 13:18 644经过多年的开发、教学 ... -
浅谈Javascript中的事件流和事件绑定
2009-08-13 16:31 812事件流 浏览器中的事 ... -
JavaScript继承详解(二)
2009-08-17 17:04 630转自:http://www.cnblogs.com/sansh ... -
JavaScript继承详解(一)
2009-08-17 17:04 709转自:http://www.cnblogs.com/sansh ... -
javascript实用技巧--数组.
2009-08-17 17:08 676数组和字符串类型对象的方法我特容易搞混淆,所以把他列出来,免得 ... -
IE和Firefox之间的JavaScript差异
2009-08-17 17:18 591尽管 JavaScript 历史上使用冗长而令人生厌的代码块来 ... -
常见的JavaScript错误
2009-08-17 17:19 748作者: Richardy, 出处:IT ... -
JS获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度
2009-08-17 17:19 671网页可见区域宽:document.body.clientWid ... -
Javascript的Defer属性
2009-08-17 17:48 733Script中的Defer属性 ... -
最佳的"addEvent"是怎样诞生的
2009-08-18 13:47 653IE的 JScript 存在内存泄露的bug 想必大家都清楚或 ... -
值得推荐的事件捕获函数AddEvent()
2009-08-18 13:56 7871, 下面是JQuery之父推荐的添加移除事件方法。 ... -
随滚动条移动的层
2009-08-20 15:55 736<!DOCTYPE html PUBLIC &qu ... -
javascript 获取滚动条高度
2009-08-20 16:02 800/******************** * 取窗口滚动 ... -
如何去掉ie里面的关闭按钮,和屏蔽ALT+F4 (转载)
2009-09-01 17:46 804去掉关闭按钮可以使用无边框窗口设计,不过IE6中已经不支持了。 ... -
(window.onunload)只有点击浏览器右上角关闭按钮才执行
2009-09-01 18:31 885<html> <head> &l ... -
带关闭按钮的页面漂浮的代码(IE/FF)
2009-09-01 18:34 706带关闭按钮的页面漂浮的代码,兼容火狐和IE,只需要把Javas ...
相关推荐
### 解开Ajax技术生命的达芬奇密码 #### 核心知识点概述 本文旨在探讨JavaScript中的面向对象编程(Object-Oriented Programming,简称OOP),特别是针对Ajax技术在Web开发中的应用。随着Ajax技术的兴起,开发者们...
li_3ck_02a_1118
基于MATLAB的牛顿迭代法实现
mellitz_3ck_01_0319
内容概要:文章阐述了银行采用人工智能(AI)技术替代传统系统的紧迫性和收益,讨论了通过构建现代化的数据和技术平台实现效率提升的方法,同时强调实施过程中确保数据质量和建立信任的重要性。文中提及,在金融行业中,若想优化业绩则必须拥抱AI带来的机遇,并为此进行经营模式的革新。根据Workday主办的研讨会内容,PwC金融服务风险与监管领导和Workday金融服务高层指出了大部分银行对AI认知不足的问题,强调AI在金融、人力资源以及IT等领域的广泛应用潜力及具体应用场景,如欺诈检测、技能映射和财务管理方面的作用。并且提到了AI部署过程中可能出现的技术与非技术难题及相应解决办法,鼓励金融机构及时投资建设新型基础设施,以保持竞争力。 适用人群:银行及其他金融机构管理人员;金融科技领域的专业研究人员;对企业数字化和智能化转型感兴趣的商业分析师、投资者;从事信息技术咨询工作的顾问。 使用场景及目标:本文可以帮助金融机构制定合理的技术发展战略规划,评估是否有必要推进AI技术转型,同时也为希望涉足银行科技项目的开发者提供了宝贵的市场洞察,帮助理解行业内普遍存在的困难与潜在的市场需求。此外,对于想要了解银行
matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
chromedriver-linux64-136.0.7058.0.zip
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
内容概要:本文档介绍了背压热电联产(CHP)发电厂的详细设计步骤,涵盖确定各状态点的压力、温度、比焓以及质量流率的具体方法。主要内容围绕计算净电功率、燃料消耗及其效率展开,并提供了T-s图绘制的指南。针对每个组件(如蒸汽轮机、冷凝器、除氧器等),都列出了详细的效率假设和压力损失表,为实际工程应用提供了宝贵的参考资料和操作指导。同时,该作业任务要求学生从给定初始值中选择合适的操作条件进行系统模拟,并利用课程讲义和Moodle平台资料完成计算流程。 适用人群:对能源转换和动力设备设计感兴趣的学生或者初涉该领域的工程师。 使用场景及目标:旨在帮助学员深入了解并掌握背压热电联产装置的工作原理和技术指标计算的方法论,通过实践练习提高他们的问题解决能力。 其他说明:文档强调了稳态运行假设的重要性,即物质平衡等于能量输入等于输出的原则,并鼓励参与者借助附录提供的典型操作参数图表来寻找解决问题的方向。此外,它还特别指出对于一些变量值求解可能需要迭代法来进行调整,直至获得稳定结果。提交的报告必须含有一份详细的T-s图和其他必要附件。
机器学习_市财政收入分析(含数据集)
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
tracy_3cd_01_0318
lusted_3cd_01_0918
题目:基于51的自动分拣系统设计 主控:AT89C52 测距模块:超声波测距模块 甲醛传感器(ADC0832+滑动变阻器模拟) 粉尘传感器(PCF8591+滑动变阻器模拟) 净化模块(继电器驱动蓝灯) 排风模块(继电器驱动绿灯) 电源电路(5V降压为3.3V供电) 显示模块(LCD1602) 声光报警 按键(3个,切换阈值选择,阈值加减) 检测物体:开关模拟 电机驱动模块(继电器驱动直流电机转动) 功能: 1.显示屏显示甲醛,粉尘浓度可以切换设置阈值。 2.通过甲醛传感器检测车间环境,大于阈值时声光报警并启动净化模块。 3.通过粉尘传感器检测车间环境,大于阈值时声光报警并启动排风模块。 4.采用超声波传感器进行物体超高监测异常(大于XX距离)时触发声光报警 5.检测到物体(开关闭合)直流电机转动(模拟传送带)
network_server
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!