`
邦者无敌
  • 浏览: 11566 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Javascript的类实现--------封装、抽象与继承

阅读更多

一.JavaScript中类的封装

      Javascript不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 下面我们以封装一个简单的Shape类来作一个说明.

     定义 ShapeBase“类”

     1.法则一[this式]

       function ShapeBase(){ 

            this.show = function(){ 

                 alert("ShapeBase show"); 

            }; 

            this.init = function(){ 

                 alert("ShapeBase init"); 

            }; 

       } 

       注:这里用到了this来声明,而不是var,后者是用来定义私有方法的。

       

       2.法则二[prototype式]

       ShapeBase.prototype.show=function(){ 

              alert("ShapeBase show"); 

       } 

       ShapeBase.prototype.init=function(){ 

              alert("ShapeBase init"); 

       }

        或者

        ShapeBase.prototype={

                  show:function(){

                          alert("ShapeBase show");

                   }

                  init:function(){

                           alert("ShapeBase init");

                   }       

        }

 

        同构造java一样,我们写一个主函数调用测试下。如下

         funciton test(){

                var s = new ShapeBase();

                s.init();

                s.show();

         }

     

        可以看到我们在构造JS类上有两中方式,在调用中我们发现其方式与java类几乎一样,new一个类对象,通过引用发送消息的形式调用具体类的方法。差别仅在于这个时候生成的类对象的类型这里还是记为var。

 

二.JS抽象类和继承

      类的封装我们已经实现了,而面向对象其他的一些优良特性我们也可以通过JS本身的特性来实现。这种化归思想本身就是一种技巧。

      我们可以利用JavaScript语言本身的性质来实现其抽象类,也可以通过将父类prototype中的成员方法复制到子类的prototype中来实现其继承机制。

      即将面向对象编程中的继承概念转化为javascript语言中的函数属性复制。

       1.JS中的实例prototype方法

      可实例化的prototype方法

          Object.prototype.extend = function(object) { 

                     return Object.extend.apply(this, [this, object]); 

          } 

       2.JS中的虚方法

      在传统语言中虚方法要先定义, 而包含虚方法的类就是抽象类,抽象类不能被实例化,但在JavaScript中,虚方法是被看作该类中未定义的方法,但已经通过this指针使用了. 所以JS中的虚方法不需经过声明而直接使用, 并且类也可以被实例化.

      静态方法:

         Object.extend = function(destination, source){ 

                for(property in source){ 

                      destination[property] = source[property]; 

                } 

                return destination; 

          }

       3.1继承[实例方法prototype]

         以object为例。先定义object的extend方法, 一个为静态方法,一个为实例方法, 这两个方法用于通过prototype来实现的继承机制。

          实现继承类Rect

          function Rect(){

                    //

          }

          // 实现继承

          Rect.prototype = ShapeBase.prototype;

          //扩充新方法

          Rect.prototype.add = function(){

                alert("Rect add");

           }

       注:这里的继承有一种区别于一般面向对象的继承特性。可能是由于prototype赋值只是简单的改变指向地址,会导致一种现象,即如果重写了“子类”的方法,则“父类”的方法也随之改变。这种权利转移的确让人惊讶。

       测试例子如下:

       如果在子类重写show方法

       Rect.prototype.show = function(){

              alert("Rect show");

       }

 

       则执行结果如下:

       function test(){

             var s = new ShapeBase();

             //结果显示:Rect show

             s.show(); 

 

              //结果显示:Rect show

             var r = new Rect();

             //结果显示:Rect add

              r.add();

       }

 

       3.2继承[静态方法]

       使用object.extend实现继承, 并实现一个oninit虚方法, 修改“父类”ShapeBase如下:

              ShapeBase.prototype = {

                        show:function(){

                                   alert("ShapeBase show");

                         }

                         initialize:function(){

                                    this.oninit();

                         }

                }

                子类Rect

                 Rect.prototype = (new ShapeBase).extend({

                             //添加新方法

                             add:function(){

                                      alert("Rect add");

                              },

                             // 重写show方法而不改变父类方法

                             show:function(){

                                      alert("Rect show");

                             },

                             //实现虚方法

                             oninit:function(){

                                     alert("Rect oninit");

                              }

                 })

 

                 测试类如下:

                 function test(src){

                         var s = ShapeBase();

                         //显示ShapeBase show[来自父类]

                         s.show();

                         var r = new Rect();

                         //显示Rect show [来自子类]

                         r.show();

                         //显示Rect add [来自子类扩充方法]

                         r.add();

                          //显示Rect oninit [来自实现的oninit方法]

                         r.initialize();

                 }

 

三.特定对象创建类

       特定对象实现属性复制
       function extend(des, src){

            if(!des){

                   des = {};

            }

            if(src){

                   for(var i in src){

                         des[i] = src [i];

                   }

            }

 

            return des;

            

       }

 

       //全局变量

       var CC = {};

       //设置create用于创建类

       CC.create = function(superclass,constructor){

               var clazz = (function(){

                      this.initialize.apply(this,arguments);

               });

                       //如果无参数,则直接返回类

                       if(arguments.length == 0){

                                 return clazz;

                       }

                       //如果父类此时constructor应该成为一个纯对象,直接复制属性返回

                       if(!superclass){

                                 extend(clazz.prototype,constructor);

                                 return clazz;

                       } 

 

                       var absObj = clazz.prototype,

                             sprPropty = superclass.prototype;

                       if(sprProty){

                             //用于访问父类方法

                             clazz.superclass  = prototype;

                             extend(absObj ,sprPropty);

                             //调用属性构造函数创建属性。实现的关键

                             extend(absObj, constructor(sprPropty));

                         //子类实例直接通过obj.superclass访问父类属性。

                        //如果不想造成过多引用,可以把这句注释掉。多数时候也没有必要

                             absObj.superclass = sprPropty;

                             clazz.constructor = constructor;

                        }

                        return clazz;

       }

      

       //创建一个动物类

       var Animal = CC.create(null ,{

                 //属性

                 footprint:‘-------------------=’,

                 //类初始化方法。当用new生成一个类时该方法自动被调用。参见上述                  //定义

                 initialize:function(options){

                         extend(this,options);

                         alert("Animal initialize method is called.");

                 }

                 eat:function(){

                          alert("Animal eat method is called");

                 }

                 move:function(){

                          alert("I am moving like this '+ this.footprint+' .");

                 }

          });

 

          //创建一个Duke类

          var Duke = CC.create(Animal,function(superclass){

                   //此处可定义类全局静态数据,该类每个实例都共享这些数据。

                   //计算实例个数,包括派生类实例

                   var static_instance_counter = 0;

                   function classUtilityFuncHere(){};

                   //返回类具体属性

                   return{

                          // 重写初始化方法

                          initialize:function(){

                                 alert("initializing Duke class");

                          }

                          //调用父类初始化。比一般其它库要简洁。

                          superclass.initialize.call(this,options);

                          //子类扩充
                          alert("Duke initialize method is called.");

                          //读取或修改类静态属性

                          static_instance_couter++;

                          

                   },

                    

                   //重写move方法并增加Duke自己的移动方式

                   move:function(){

                          this.footprint = this.footprint + "zzzzzzzzzzzzz";

                          superclass.move.call(this);

                   },

                   //重写eat方法,覆盖父类eat方法

                   eat:function(){

                          alert("Duke is eating");

                   },

                   //子类新增自己的方法,显示当前已经初始化的Duke类实例数量

                   say:function(){

                         alert("The number of Duke instance is ' + static_instance_counter' ");

                   }

          };

 

          });

 

          var DukeChild = CC.create(Duke,function(superclass){

                   return{

                           move:function(){

                                  this.footprint = this.footprint + "++++++=";

                                  superclass.move.call(this);

                           },

                           say:function(){

                                  alert("this.msg ||");

                           }

                   };

 

           })

 

           测试类:

           function test(){

                 var animal = new Animal();

                 animal.eat()

                 animal.move();

                 var dukeA = new Duke();

                 dukeA.eat();

                 dukeA.move();

                 dukeA.say();

                 var dukeB = new Duke();

                 dukeB.eat();

                 dukeB.move();

                 dukeB.say();

                 var dukeC = new DukeChild({msg:'I am a child of duke'});

                 duckC.move();

                 duckC.say();

           }

 

 

分享到:
评论

相关推荐

    JavaScript 继承 封装 多态实现及原理详解

    所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个...

    (全)传智播客PHP就业班视频完整课程

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    史上最全韩顺平传智播客PHP就业班视频,10月份全集

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    史上最全传智播客PHP就业班视频课,8月份视频

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    史上最全韩顺平传智播客PHP就业班视频,9月份全集

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    玩转JavaScript OOP – 类的实现详解

    但是JavaScript的函数功能非常灵活,其中之一就是构造函数,结合构造函数和原型对象可以实现”类”。 对象和类的概念 对象 “对象”是面向对象编程中非常重要的一个概念,一个对象是一个“东西”(某个人或某件事)...

    Javascript基于对象三大特性(封装性、继承性、多态性)

    Javascript基于对象的三大特征和C++,Java面向对象的三大特征一样,都是封装(encapsulation)、继承(inheritance )和多态(polymorphism )。只不过实现的方式不同,其基本概念是差不多的。其实除三大特征之外,还有一...

    韩顺平PHP JS JQUERY 所有视频下载种子 货真价实

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    worldwindjava源码-javascript-oop:面向对象编程和面向对象JavaScript

    世界风java源码JavaScript ...抽象是一个与封装密切相关的概念。 这也是一种消除复杂性的方法。 想想你的手机。 它有一个非常简单的用户界面:也许它有一个屏幕和一个按钮(甚至可能没有一个按钮!)

    java从入门到精通70个PPT

    8.接口与抽象类 9.java集合类 10.jdbc 11 html简介与js的基本语法 12 javascript内置对象和内置函数 13 javascript的DOM编程 14-15项目案例:当当网上书店或者做一个计算器 16 Ajax 原理 17 Ajax框架 18 在线培训:...

    php网络开发完全手册

    5.5 类的引用、扩展与继承 75 5.5.1 类的引用 75 5.5.2 类的扩展与继承 76 5.6 操作与调用 77 5.6.1 静态类的调用 77 5.6.2 实例类型的判断方法instanceof 78 5.6.3 对象的克隆 78 5.7 一些设计观念 80 5.7.1 策略...

    asp.net知识库

    .net 2.0 访问Oracle --与Sql Server的差异,注意事项,常见异常 Ado.net 与NHibernate的关系? 动态创建数据库 SQL Server数据库安全规划全攻略 .net通用数据库访问组件SQL Artisan应用简介1 在Framework1.0下...

    asp.net面试题

    类与结构有很多相似之处:结构可以实现接口,并且可以具有与类相同的成员类型。然而,结构在几个重要方面不同于类:结构为值类型而不是引用类型,并且结构不支持继承。结构的值存储在“在堆栈上”或“内联”。细心的...

    JavaScript设计模式:ES5 + ES6 + CoffeeScript + TypeScript设计模式,其中包含一些理论,实际示例和UML图

    PatternifyJS-JavaScript设计模式关于PatternifyJS是JavaScript中主要设计模式的... 因此,这种样式大量使用了包,抽象,接口,类,继承,组成,封装和多态性。 作为一种基于原型的语言,JavaScript本身并不具备所有

    写给大家看的面向对象编程书(第3版).[美]Matt Weisfeld(带详细书签).pdf

    2.1 了解接口与实现之间的区别 28 2.1.1 接口 29 2.1.2 实现 29 2.1.3 接口/实现示例 29 2.2 设计接口时使用抽象思维 33 2.3 尽可能为用户提供最小接口 35 2.3.1 确定用户 35 2.3.2 对象行为 36 2.3.3 环境...

    PUCES-2021-FEB-DESIGN-PATTERNS

    复发性问题的复发性解决方案面向对象的程序设计OOP的构建块:抽象,多态,封装和继承不良结果:耦合类,上帝类,巨大的继承链,纠结的代码,超细粒度的OOP反对设计模式的争论弱编程语言低效的解决方案不正当使用...

    学习javascript面向对象 理解javascript对象

    封装:隐藏实现细节,实现代码模块化 继承:扩展已存在的代码模块,实现代码重用  多态:接口的不同实现方式,实现接口重用 四、对象定义:无序属性的集合,其属性可以包含基本值、对象或者函数 //简单的对象实例...

    程序员面试刷题的书哪个好-JavaScriptProgress:JS进阶

    抽取(抽象)对象共用的属性和行为组织(封装)成一个类(模板); 对象实例化,获取类的对象; 对象 万物皆对象 对象由属性和方法组成 属性:事物的特征(名词) 方法:事物的行为(动词) 类 ES6中增加了类class...

    Javascript OOP之面向对象

    一般面向对象包含:继承,封装,多态,抽象 对象形式的继承 浅拷贝 var Person = { name: 'allin', age: 18, address: { home: 'home', office: 'office', } sclools: ['x','z'], }; var programer

    Object-Oriented-Programming:Muzaffer Arda Uslu 创建的 C++ 面向对象编程

    OOP与诸如类,对象,继承,封装,抽象,多态等概念相关联。什么是方法和属性(属性)? 方法是可以对对象执行的操作。 属性保存数据并帮助识别对象。什么是班级? 类基本上是一个包含变量和方法的代码块。

Global site tag (gtag.js) - Google Analytics