JavaScript 类的封装操作示例详解

本文实例讲述了JavaScript 类的封装操作。分享给大家供大家参考,具体如下:

一,首先,为什么要使用封装?

这是从信息的角度出发的,信息的隐藏是最终的目的,而封装只不过是实现隐藏的一种方法。

这里我们需要明白一点就是:类的定义有如下的三种方式:

(第一种)门户大开型方式       (第二种)用命令规范区别私有和公有的方式    (第三种)闭包

现在详细描述一下每一种类的定义方式:

针对第一种,门户大开类型

首先,我们来看一种情况

(1)声明一个简单的类,代码如下

 function Person(age,name) {
    this.name=name;

    this.age=age;
  }

  (2)实例化类+调用

var p=new Person(-10,"小明");
alert(p.age)//结果出现年龄出现负数

  从上述的运行结果中,我们可以看出程序可以正常执行,但这并符合实际,因为年龄出现 了负数,这不是我们想要的,我们需要一个能正确处理并产生与实际情况相符的解决方案。

为了能解决上述年龄出现的问题,我们可以这样做:扩展类的原型链

Person.prototype={
    checkAge:function (age) {
     if(0<age&&age<150){
       return true;
     }else {
      return false;
        }
          }
       }

加上解决方案后,代码如下

(1)基本类

 function Person(age,name) {
    this.name=name;
    //调用方法判断验证
    if(!this.checkAge(age)){
      throw new Error("年龄必须在0-150之间");
    }
    this.age=age;
  }

(2)年龄判断验证

 Person.prototype={
          checkAge:function (age) {
            if(0<age&&age<150){
              return true;
            }else {
              return false;
            }
          }
      }

(3)调用

var p2=new Person(10,"小明");
alert(p2.age)

我们还可以给name添加一个读取验证,name为空时使用默认值 同样是扩展类的原型链

代码如下,

 Person.prototype["getName"]=function () {
        return this.name||"我是默认的";
      }
//调用
var p3=new Person(10,"");
alert(p3.getName())//结果为“我是默认的”

总结一下:当类被定义为门户大开类型时会出现与实际不符合的情况 ,虽然我们可以加在类上扩展原型类加验证方法解决,但是这样会使类变得臃肿。

针对第二种,用命名规范区别私有和公有

步骤如下,

(1)定义类 在类中定义变量(私有和公有变量)+验证方法的调用

//用命名规范来区别私有和公有
  function Person(name,age,email) {
    //定义私有变量

    this._name;//私有
    this.setName(name);//只是方法的调用,方法中有验证,而不是在类中验证

    this._age;//私有
    this.setAge(age);
     this.email=email;//公有的
  }

(2)在类的原型上面 扩展赋值方法

Person.prototype={//直接扩展至原型上,可以在本类的内部使用this调用
    setName:function (name) {
    this._name=name;
    },
    setAge:function (age) {
      //需要做判断符号实际情况
      if(age>0&&age<150){//验证不在类中,类不会变的臃肿
        this._age=age;
      }else {
        throw new Error("年龄必须是在0到150范围内")
      }
    }

  }

(3)应用

var text1=new Person("测试",-10,"qq.com");
 alert(text1._age)//-10 程序会报错 这是我们想要的(说明验证是对的)
 var p2=new Person("测试2",10,"qq.cpm");
  alert(p2._age)//程序正常运行 达到我们的目标

总结一下:在类的定义是使用命名规范来定义私有变量和公有变量,并将验证方法和赋值方法扩展到本类的原型链上,在类中调用方法即可(会有返回值),这样不会导致类的臃肿。

针对第三种,闭包实现封装

这种方式有点像高级语言,在定义类是使用get,set方法实现数据的操作

(1)定义一个基本类(变量+操作变量的方法)

  function Person(name,age,email) {
    //(1)声明变量和对变量进行操作的get和set方法
    this.email=email;//公有变量
    //get方法
    this.getName=function (name){
      return this.name;//为什么是this调用呢?请看set方法
    }
    this.getAge=function (age){
      return this.age;
    }
    //set方法 这里相当于在类上的扩展
    this.setName=function (name) {
      this.name=name;//Person.prototype.name 这里写明了get中this的写法的来源
    }
    this.setAge=function (age) {
      if(age>0&&age<150){
        this.age=age;//Person.prototype.name 这里写明了get中this的写法的来源
      }else {
        throw new Error("年龄必须是在0到150范围内");
      }
    }

    //(2)写一个构造函数 做初始化 实现闭包 确保set是在get之前的,不然get时会出现错误
    this.init=function () {
     this.setName(name);
     this.setAge(age);
    }
    this.init();//显示调用
  }

(2)应用

var p=new Person("text",-10,"qq.com");
  alert(p.age)//程序由于不符合实际而被阻断,符合要求

注:额外的闭包写法   var 方式

 var _sex="M";
    this.getSex=function () {
       return _sex;
    }
    this.setSex=function () {
        _sex=sex;
    }

总结一下:

(1)这里只是函数和属性的简单封装,还有更为复杂是业务需要封装,使用get和set方法时,需要一个构造函数用于两者先后顺序的初始化实现闭包,之后显示调用,确保set是在get之前的。

(2)闭包的实现,是通过get和set实现的,this.方式赋值时没有暴露在外面而是通过get,set方法实现闭包。

二,静态化

普通属性和函数是作用在对象上到,而静态函数是定义到类上的。

第一种静态函数的写法 :写在类上

(1)首先,定义一个简单的类,例如

 function Person(name,age) {
    this.name=name;
    this.age;age;
    this.showName=function () {
      alert(this.name);
    }
  }

(2)定义一个写在类上的方法,Person.add --》(类.函数)或者(类.属性),例如

 Person.add=function (x,y) {
    return x+y;
  }

(3)应用

alert(Person.add(10,20));//结果为30

总结一下,该种定义方式有点类似于高级语言的静态类,使用与高级语言的相同通过类直接调用。

第二种静态函数的写法 :使用类中类的方式完成每一个对象全拥有当前类中相同的属性和函数 。注意:  类中类的方式是一次性赋值的

(1)类的定义格式如下

var cat=(function () {
    //私有静态属性
     var AGE=1;
     function add(x,y) {
       return x+y;
     }

     return function () {//类中类 return返回的类中持有与上面类中相同的属性与函数 则共同的AGE和add称为静态属性和静态函数
       this.AGE=AGE;
       this.add=function (x,y) {
        return add(x,y)
       }
     }
  })()//实例化cat,实质是通过return实例化的

(2)应用

 alert(new cat().add(1,3))//4
 alert(new cat().AGE)//1

总结一下:从上面的代码格式中我们不难看出在一个类中定义有私有的属性和方法,与一个返回可以初始化本类私有静态属性和方法的类,该类我们称为类中类。当我们实例化外层类时实质上是通过该类内部的类return实例化的。

封装的优点:

(1)保护内部数据完整性是封装一大用处
(2)对象的重构变得轻松,(如果没有封装你敢动正在运用的代码吗?) 答案肯定是不敢的。
(3)化模块间的耦合

弊端:

(1)私有的方法会变得难以进行单元测试
(2)使用封装意味着与复杂的代码打交道
(3)最大问题封装在JavaScript中很难实现  除非运用自如,否则到处封装,使测试变得困难。

以上只是学习的初步理解,不好还希望多多理解。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

(0)

相关推荐

  • JS类的封装及实现代码

    1. 定义js类 js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. 复制代码 代码如下: function ShapeBase() { this.show = function() { alert("ShapeBase show"); }; this.init = function(){ alert("ShapeBase init&q

  • javascript面向对象包装类Class封装类库剖析

    javascript是个入门门槛很低的语言,甚至一个从来没有接触过javascript的技术人员,几小时内就可以写出一个简单有用的程序代码. 但是如果因此你就下结论:javascript是门简单的语言.那你就大错特错了.想写出高性能的代码,同样需要具备一个高级程序员的基本素养. 一个java或者c++程序员,不一定能写出高性能的javascript代码,但更容易写出高性能的javascript代码. javascript的简单是基于它"胸襟广阔"的包容性.它声明时,不需要指定类型,甚至

  • 封装了一个自动生成渐变字的JS类(clip)

    你需要做的只是在HTML页面里面把需要用到渐变色的文字加上外容器(span标签或者a标签都可以),再给这个标签加入name属性做渐变元素的标示,rel属性指示渐变的颜色,rel属性的格式很重要: 复制代码 代码如下: rel="#十六进制颜色-#十六进制颜色" 少一个或多一个字符都不行. CSS+JS多彩渐变字 body{font:12px/1.5 arial} h3{padding:10px;margin:0;background-color:#c00;border:1px dash

  • js类的继承定义与用法分析

    本文实例讲述了js类的继承定义与用法.分享给大家供大家参考,具体如下: 如何实现类的继承呢? 有如下2个构造函数: function PeopleClass(){ this.type = "人"; }; PeopleClass.ptototype = { getType:function(){ alert("这是一个人"); } }; function StudentClass(name,sex){ this.name = name; this.sex = sex;

  • 详解javascript常用工具类的封装

    前言 因为工作中经常用到这些方法,所有便把这些方法进行了总结. JavaScript 1. type 类型判断 isString (o) { //是否字符串 return Object.prototype.toString.call(o).slice(8, -1) === 'String' } isNumber (o) { //是否数字 return Object.prototype.toString.call(o).slice(8, -1) === 'Number' } isObj (o) {

  • 常用JavaScript代码提示公共类封装

    希望对大家有帮助! 复制代码 代码如下: using System; using System.Web; namespace Jake.PublicJS { /// <summary> /// Summary description for PublicJS /// </summary> public class PublicJS { public PublicJS() { // // TODO: Add constructor logic here // } /// <su

  • JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】

    本文实例讲述了JavaScript 面向对象程序设计.分享给大家供大家参考,具体如下: 类的创建于实例对象 工厂模型创建对象 function CreatePerson ( name,sex,age ) { var obj = new Object(); obj.name = name; obj.sex = sex; obj.age = age; obj.sayName = function () { console.log( this.name ); } return obj; } var p

  • js提取中文拼音首字母的封装工具类

    前言 本文主要记录了如何用js提前中文拼音首字母的方法.封装一个函数,假如有需要的,可以直接拿去用.下面话不多说了,来一起看看详细的介绍吧. 原理 主要是根据中文的unicode码来进行的.主要是在收集的中文范围内查找,大家可以多收集一些.假如中文是多音字,那可能有点坑了! var getPy = (function() { //函数使用,本表收录的字符的Unicode编码范围为19968至40869, XDesigner 整理 var strChineseFirstPY = "YDYQSXMW

  • js定义类的方法示例【ES5与ES6】

    本文实例讲述了js定义类的方法.分享给大家供大家参考,具体如下: 以下是es5标准里定义类的方法: <script> function Point(x,y){ this.x=x; this.y=y; } Point.prototype.toString=function(){ return '('+this.x+', '+this.y+')'; } var point=new Point(1,2); console.log(point); </script> 运行结果: 上面这样用

  • javascript封装的sqlite操作类实例

    本文实例讲述了javascript封装的sqlite操作类.分享给大家供大家参考.具体如下: function sql(name,v,desc,size,tables){ this.db=null; this.name=name; this.v=v; this.desc=desc; this.size=size; this.tables=tables; this.ini(); } sql.prototype.ini=function(){ var self=this; self.db=openD

  • JavaScript ES6 Class类实现原理详解

    JavaScript ES6之前的还没有Class类的概念,生成实例对象的传统方法是通过构造函数. 例如: function Mold(a,b){ this.a=a; this.b=b; } Mold.prototype.count=function(){ return this.a+this.b; }; let sum=new Mold(1,2); console.log(sum.count()) //3 这中写法跟传统的面向对象语言差异较大,写起来也比较繁杂. ES6提供了更加接近其他语言的

随机推荐