javascript关于面向对象的总结

来源:互联网 发布:遥知不是雪为有暗香来 编辑:程序博客网 时间:2024/05/19 01:11
对于javascript大家大部分时间用来做效果,但却忽视了最基础的东西,
当大家把javascript基本功学扎实了,我认为对以后写出漂亮的js代码有很大的帮助,
今天就总结下我对javascript关于面向对象方面的理解
首先总结一下javascript中的"类",
第一种算是比较灵活的方式了,成为工厂定义方式
  1. var obj=new Object;
  2. obj.color='red';
  3. obj.dodo=function(){...};

为什么说它灵活,就是因为它可以在实例化对象后,可以对该对象增加属性,可以完善我们的需求,
我们经常会得到实例化的对象比如:=var aa=document.getElementById('lover'),此时我们可以很方便的增加各种方法属性,
aa.onclick=function(){...};aa.lover='i love you ';等,以至传递的时候只需要传递该对象;
 
  1. <script   language= "javascript">
  2. var obj=new Object;
  3. obj.color='red';
  4. obj.dodo=function(){alert('aa')};
  5. for(aa in obj)
  6. {
  7. alert(aa);//color;dodo;
  8. }
  9. </script> 



javascript中定义类我们平时都是按照这种方式,因为毕竟和java和c#比较接近,
  1. function Car(scolor,snum)
  2. {
  3. this.color=scolor;
  4. this.dodo=function(){alert('aa')};
  5. }
  6. //这叫做构造函数方式定义类
  7. var obj=new Car('yellow',30);
  8. for(aa in obj)
  9. {
  10. alert(aa);//color;dodo
  11. }

上面不用多介绍大家是最熟悉的了,

接下来介绍原型方式:
什么是原型,关于具体的概念大家可以查看资料,不想说太多,只想举例子来说明,
 
  1. <script   language= "javascript">
  2. function Car(scolor,snum)
  3. {
  4. this.color=scolor;
  5. this.dodo=function(){alert('aa')};
  6. }
  7. Car.prototype.getValue = function (){
  8. return this.color;
  9. }
  10. Car.prototype.setValue = function (value){
  11. this.color = value;
  12. }
  13. var obj=new Car('yellow',30);
  14. obj.setValue(666);
  15. alert(obj.getValue());//666
  16. for(aa in obj)
  17. {
  18. alert(aa);//color;dodo;setValue;getValue
  19. }
  20. </script> 

可以看到利用原型可以为对象增加属性和方法,具体为什么要利用原型来操作,概念性的问题可以查资料,
但是有一点需要注意的是:
  1. <script   language= "javascript">
  2. function Car(scolor,snum)
  3. {
  4. //this.cc="cc";
  5. //this.docc=function(){alert(this.cc)}
  6. }
  7. Car.prototype.cc = "cccc"
  8. Car.prototype.docc = function (){alert(this.cc)}
  9. var obj=new Car('yellow',30);
  10. for(aa in Car.prototype)
  11. {
  12. alert(aa);//cc;docc
  13. }
  14. alert(obj.cc);
  15. obj.docc();
  16. </script> 

虽然同样是给对象增加了cc属性和docc方法,但是查找顺序是先查找构造函数中是否有该属性和方法,
没有再搜索propertype,根据
  1. <script   language= "javascript">
  2. function Car(scolor,snum)
  3. {
  4. this.cc="cc";
  5. this.docc=function(){alert(this.cc)}
  6. }
  7. Car.prototype.cc = "cccc"
  8. Car.prototype.docc = function (){alert(this.cc)}
  9. var obj=new Car('yellow',30);
  10. alert(obj.cc);//cc
  11. delete obj.cc;
  12. alert(obj.cc);//cccc
  13. obj.docc();//cccc
  14. delete obj.docc();
  15. obj.docc();//cccc
  16. </script> 

可以看到首先删除两个属性仍然可以输出属性值,并且第一个obj.docc()获取的是原型中的cc属性值

看下面的例子:
 
  1. <script   language= "javascript">
  2. function Car(scolor,snum)
  3. {
  4. this.cc="cc";
  5. }
  6. Car.prototype.cc = "cccc"
  7. Car.prototype.docc = function (){alert(this.cc)}
  8. var obj=new Car('yellow',30);
  9. Car.prototype.docc();//cccc
  10. </script> 

可以直接调用原型方法,调用的是原型中的cc属性而不是构造函数的,
如果没有定义原型cc属性,就会显示undefined,在直接调用原型方法时这是需要注意的地方
再然后介绍一下javascript静态的实现方法:
  1. <script   language= "javascript">
  2. function Car()
  3. {
  4. Car.docc = function (){alert('cc')}
  5. }
  6. Car.docc = function (){alert('cccc')}
  7. Car.docc();//cccc
  8. var obj=new Car();//初始化后构造函数中的静态方法覆盖外边定义的静态方法,需要注意!
  9. Car.docc();//cc
  10. </script> 



在了解以上基本概念以后,接下来介绍一下javascript如何实现继承,
我们知道所有的对象都是继承objec类,而javascript中是怎样继承了object类呢?
其实在javascript中隐藏了
  1. Car.prototype = new Object();
作用是什么呢?很明显Object中有toString()方法,
这样
  1. Car.paopertype.toString()=function(){...}
  2. //是不是就显而易见了,在实例化Car可以成功的引入该属性,而Object中的所有属性和方法都归了Car,就这样Car继承了Object的所有属性和方法。
  3. <script   language= "javascript">
  4. function Car(scolor,snum)
  5. {
  6. this.cc="cc";
  7. }
  8. alert(Car.toString());
  9. </script> 
上面的例子不是太贴切,我补充一个大家看看

  1. <script   language= "javascript">
  2. function obj()
  3. {
  4. this.aa='aa';
  5. this.bb=function(){alert('==========')};
  6. }
  7. function Car()
  8. {
  9.  this.cc="cc";
  10. }
  11. Car.prototype = new obj();
  12. var aa=new Car();
  13. for(a in aa)
  14. {
  15. alert(a);//aa;bb;cc
  16. }
  17. aa.bb();
  18. for(b in Car.prototype)
  19. {
  20. alert(b);//aa;bb
  21. }
  22. </script> 
这样大家就能明白
  1. Car.prototype = new obj();
这句话的含义了。

接下来又引出一个重要属性,constructor,

  1. <script   language= "javascript">
  2. function Car(scolor,snum)
  3. {
  4. this.cc="cc";
  5. }
  6. alert(Car.prototype.constructor);//constructor就是指向自己本身的一个属性
  7. </script> 


再看下面
  1. <script   language= "javascript">
  2. function Car(scolor,snum)
  3. {
  4. this.cc="cc";
  5. }
  6. Car.prototype.cc = "cccc"
  7. Car.prototype.docc = function (){alert(this.cc)}
  8. alert(Car.prototype.constructor.prototype.cc);//cccc
  9. Car.prototype.constructor.prototype.docc();//cccc
  10. alert(Car.prototype.constructor===Car);//true
  11. </script> 

大家看结果明白了吧

还有让大家比较头疼的问题就是call和apply的用法,
首先给大家做个解释,
  1. function classA(scolor){
  2. this.docc=function(){...}
  3. }
  4. function classB(){
  5. //this.newMethod=classA;
  6. //this.newMethod(scolor);
  7. //delete this.newMethod();
  8. //这三行与下面的call是一个效果,通过这个例子大家就应该明白call具体是怎样执行的了,等同于上面三行的实现,
  9. 一句this.newMethod(scolor);函数调用,就将classA中的关于this.的方法和属性就都归classB,因为此时classA中的
  10. this指针在classB内部指向的就是classB本身,所以这也是实现继承的一种手段,
  11. classA.call(this,scolor);
  12. }

完整的例子:
  1. <script   language= "javascript">
  2. function classA(scolor){
  3. this.cc=scolor;
  4. this.docc=function(){alert(this.cc)}
  5. }
  6. function classB(){
  7. classA.call(this,"yellow");
  8. }
  9. var obj=new classB();
  10. alert(obj.cc)//yellow
  11. obj.docc();//yellow
  12. </script>
此时大家想原型方法能够继承吗?其实就按照我上面的解释,大家也该明白函数调用this.newMethod(scolor)只调用函数本身,就象我们平时使用函数一样,不会牵扯到原型上去,所以
  1. <script   language= "javascript">
  2. function classA(scolor){
  3. this.cc=scolor;
  4. this.docc=function(){alert(this.cc)}
  5. }
  6. classA.prototype.dd = "dddd"
  7. classA.prototype.dodd = function (){alert(this.dd)}
  8. function classB(){
  9. classA.call(this,"yellow");
  10. }
  11. var obj=new classB();
  12. alert(obj.dd)//undefined
  13. obj.dodd();//出错没有该方法
  14. </script> 


那我们怎么办呢?很简单,只要仔细看了我上面的介绍,
  1. <script   language= "javascript">
  2. function classA(scolor){
  3. this.cc=scolor;
  4. this.docc=function(){alert(this.cc)}
  5. }
  6. classA.prototype.dd = "dddd"
  7. classA.prototype.dodd = function (){alert(this.dd)}
  8. function classB(){
  9. }
  10. classB.prototype = new classA("yellow");
  11. var obj=new classB();
  12. alert(obj.cc)//yellow
  13. obj.docc();//yellow
  14. alert(obj.dd)//dddd
  15. obj.dodd();//dddd
  16. </script> 

我再给大家举个合用的例子
  1. <script   language= "javascript">
  2. function classA(scolor){
  3. this.cc=scolor;
  4. this.docc=function(){alert(this.cc)}
  5. }
  6. classA.prototype.dd = "dddd"
  7. classA.prototype.dodd = function (){alert(this.dd)}
  8. function classB(){
  9. classA.call(this,"red");//初始化red后继承
  10. }
  11. classB.prototype = new classA("yellow");//初始化yellow后继承
  12. var obj=new classB();
  13. alert(obj.cc)//red
  14. obj.docc();//red
  15. alert(obj.dd)//yellow
  16. obj.dodd();//yellow
  17. </script> 

为什么会是red不是yellow原因很简单,一个是在构造函数内实现了继承,一个是原型继承,而我们说过构造函数在
原型之前调用,所以会出现red而不是yellow。

最后借助风之石写的一个例子结束此次文章:
  1. <html>
  2. <body>
  3. <button id=btTest>test</button>
  4. </body>
  5. </html>
  6. <script>
  7. if(!document.all){
  8.     HTMLElement.prototype.attachEvent=function(sType,foo){
  9.         this.addEventListener(sType.slice(2),foo,false)
  10.     }
  11. }
  12. Function.prototype.bindNode=function(oNode){
  13.     var foo=this,iNodeItem
  14.     //使用了全局数组__bindNodes,通过局部变量iNodeItem进行跨函数传值,如果直接传送oNode,也将造成闭包
  15.     if(window.__bindNodes==null)
  16.         __bindNodes=[]
  17.     __bindNodes.push(oNode)
  18.     iNodeItem=__bindNodes.length-1
  19.     //释放oNode
  20.     oNode=null
  21.     return function(e){
  22.         foo.call(__bindNodes[iNodeItem],e||event)
  23.              //需要注意的是调用了call本身就是一个调用了foo()函数的过程,所以上面返回的是一个函数
  24.     }
  25. }
  26. abc()
  27. function abc(){
  28.     var bt=document.getElementById("btTest")
  29.     bt.attachEvent("onclick",function(){
  30.         //如果不经过bindNode处理,下面的结果将是undefined
  31.         alert(this.tagName)
  32.     }.bindNode(bt))
  33.     //释放bt
  34.     bt=null
  35. }
  36. </script>
大家可以自己回味一下call的用法,不明白或者有错误可以在回复中指出,匆匆忙忙写完一定会有不足之处,
请指教