JavaScript 类的封装操作示例详解


Posted in Javascript onMay 16, 2020

本文实例讲述了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.3water.com/code/HtmlJsRun测试上述代码运行效果。

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

Javascript 相关文章推荐
另类调用flash无须激活的方法
Dec 27 Javascript
js中的this关键字详解
Sep 25 Javascript
jquery简单倒计时实现方法
Dec 18 Javascript
jQuery插件passwordStrength密码强度指标详解
Jun 24 Javascript
JavaScript 字符串常用操作小结(非常实用)
Nov 30 Javascript
easyui关于validatebox实现多重规则验证的方法(必看)
Apr 12 Javascript
微信JS-SDK选取手机照片上传功能
Apr 21 Javascript
简述jQuery Easyui一些用法
Aug 01 jQuery
es6学习之解构时应该注意的点
Aug 29 Javascript
静态页面实现 include 引入公用代码的示例
Sep 25 Javascript
React Native AsyncStorage本地存储工具类
Oct 24 Javascript
浅谈vue中慎用style的scoped属性
Nov 28 Javascript
jquery+css3实现的经典弹出层效果示例
May 16 #jQuery
js抽奖转盘实现方法分析
May 16 #Javascript
JSONP 的原理、理解 与 实例分析
May 16 #Javascript
JavaScript随机数的组合问题案例分析
May 16 #Javascript
Taro UI框架开发小程序实现左滑喜欢右滑不喜欢效果的示例代码
May 18 #Javascript
vue el-tree 默认展开第一个节点的实现代码
May 15 #Javascript
基于leaflet.js实现修改地图主题样式的流程分析
May 15 #Javascript
You might like
为什么夜间收到的中波电台比白天多
2021/03/01 无线电
PHP实现上一篇下一篇的方法实例总结
2016/09/22 PHP
php版微信小店API二次开发及使用示例
2016/11/12 PHP
PHP实现的二分查找算法实例分析
2017/12/19 PHP
JavaScript创建一个欢迎cookie弹出窗实现代码
2013/03/15 Javascript
通过js获取div的background-image属性
2013/10/15 Javascript
使用jquery+CSS实现控制打印样式
2014/12/31 Javascript
js和jquery分别验证单选框、复选框、下拉框
2015/12/17 Javascript
json与jsonp知识小结(推荐)
2016/08/16 Javascript
js将字符串中的每一个单词的首字母变为大写其余均为小写
2017/01/05 Javascript
基于vue+ bootstrap实现图片上传图片展示功能
2017/05/17 Javascript
Vue使用枚举类型实现HTML下拉框步骤详解
2018/02/05 Javascript
详解Vue iview IE浏览器不兼容报错(Iview Bable polyfill)
2019/01/07 Javascript
[05:31]干嘛呢兄弟!DOTA2 TI9语音轮盘部分出处
2019/05/14 DOTA
10款最好的Web开发的 Python 框架
2015/03/18 Python
在Django中创建动态视图的教程
2015/07/15 Python
使用pyecharts无法import Bar的解决方案
2020/04/23 Python
python分析作业提交情况
2017/11/22 Python
Python连接Mssql基础教程之Python库pymssql
2018/09/16 Python
用Python编写一个高效的端口扫描器的方法
2018/12/20 Python
Django REST framework内置路由用法
2019/07/26 Python
使用Python调取任意数字资产钱包余额功能
2019/08/15 Python
在 Jupyter 中重新导入特定的 Python 文件(场景分析)
2019/10/27 Python
Python多进程编程multiprocessing代码实例
2020/03/12 Python
Python基于Hypothesis测试库生成测试数据
2020/04/29 Python
virtualenv介绍及简明教程
2020/06/23 Python
Keras模型转成tensorflow的.pb操作
2020/07/06 Python
CSS3效果:自定义“W”形运行轨迹实例
2017/03/29 HTML / CSS
canvas 如何绘制线段的实现方法
2018/07/12 HTML / CSS
转预备党员政审材料
2014/02/06 职场文书
喜之郎果冻广告词
2014/03/20 职场文书
2014大学生职业生涯规划书最新范文
2014/09/13 职场文书
交通肇事罪辩护词
2015/05/21 职场文书
个人职业生涯规划之自我评估篇
2019/09/03 职场文书
python实现A*寻路算法
2021/06/13 Python
Python 实现Mac 屏幕截图详解
2021/10/05 Python