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 相关文章推荐
js获取变量
Aug 24 Javascript
javascript使用isNaN()函数判断变量是否为数字
Sep 21 Javascript
禁止拷贝网页内容的js代码
Jan 22 Javascript
JavaScript实现继承的4种方法总结
Oct 16 Javascript
javascript函数式编程实例分析
Apr 25 Javascript
浅析javascript的return语句
Dec 15 Javascript
Vue.js手风琴菜单组件开发实例
May 16 Javascript
关于HTML5的data-*自定义属性的总结
May 05 Javascript
微信小程序实现日历效果
Dec 28 Javascript
vue模式history下在iis中配置流程
Apr 17 Javascript
webpack结合express实现自动刷新的方法
May 07 Javascript
原生js实现下拉框选择组件
Jan 20 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
php适配器模式介绍
2012/08/14 PHP
PHP获取当前日期和时间及格式化方法参数
2015/05/11 PHP
PHP的PDO预处理语句与存储过程
2019/01/27 PHP
CI框架简单分页类用法示例
2020/06/06 PHP
可以把编码转换成 gb2312编码lib.UTF8toGB2312.js
2007/08/21 Javascript
JavaScript 仿关机效果的图片层
2008/12/26 Javascript
location.search在客户端获取Url参数的方法
2010/06/08 Javascript
JS 修改URL参数(实现代码)
2013/07/08 Javascript
对于Form表单reset方法的新认识
2014/03/05 Javascript
jQuery实现表格展开与折叠的方法
2015/05/04 Javascript
举例详解JavaScript中Promise的使用
2015/06/24 Javascript
BootStrap下jQuery自动完成的样式调整
2016/05/30 Javascript
Bootstrap3使用typeahead插件实现自动补全功能
2016/07/07 Javascript
原生ajax处理json格式数据的实例代码
2016/12/25 Javascript
Bootstrap标签页(Tab)插件使用方法
2017/03/21 Javascript
原生js简单实现放大镜特效
2017/05/16 Javascript
JavaScript模拟实现封装的三种方式及写法区别
2017/10/27 Javascript
JS弹窗 JS弹出DIV并使整个页面背景变暗功能的实现代码
2018/04/21 Javascript
微信小程序页面调用自定义组件内的事件详解
2019/09/12 Javascript
js实现视图和数据双向绑定的方法分析
2020/02/05 Javascript
vue3.0 的 Composition API 的使用示例
2020/10/26 Javascript
MySQL最常见的操作语句小结
2015/05/07 Python
Jupyter安装nbextensions,启动提示没有nbextensions库
2020/04/23 Python
Python的条件表达式和lambda表达式实例
2019/01/31 Python
Python获取Redis所有Key以及内容的方法
2019/02/19 Python
mac系统下Redis安装和使用步骤详解
2019/07/09 Python
如何用Python破解wifi密码过程详解
2019/07/12 Python
Python远程开发环境部署与调试过程图解
2019/12/09 Python
pytorch AvgPool2d函数使用详解
2020/01/03 Python
python读取与处理netcdf数据方式
2020/02/14 Python
python 8种必备的gui库
2020/08/27 Python
python 实现控制鼠标键盘
2020/11/27 Python
英国领先的家庭时尚品牌:Peacocks
2018/01/11 全球购物
Glamest意大利:女性在线奢侈品零售店
2019/04/28 全球购物
大学迎新晚会主持词
2014/03/24 职场文书
贷款工资证明范本
2015/06/12 职场文书