理解javascript封装


Posted in Javascript onFebruary 23, 2016

封装可以被定义为对对象的内部数据表现形式和实现细节进行隐藏。通过封装可以强制实施信息隐藏。

在JavaScript中,并没有显示的声明私有成员的关键字等。所以要想实现封装/信息隐藏就需要从另外的思路出发。我们可以使用闭包的概念来创建只允许从对象内部访问的方法和属性,来达到封装的要求。

基本方式
一般来说,我们学用的有三种方法来达到封装的目的。

使用this.XXX来声明一个变量,然后再声明getXXX、setXXX等取值、赋值的方法。
使用this._XXX来声明一个变量,然后再声明getXXX、setXXX等取值、赋值的方法。
利用“函数作用域”这一个概念来做。
1. 门户大开型

var Book = function(isbn,title,author){
 this.setIsbn(isbn);
 this.setTitle(title);
 this.setAuthor(author);
};

Book.prototype = {
 setIsbn: function(isbn){
  this.isbn = isbn;
 },
 getIsbn: function(){
  return this.isbn;
 },
 setTitle: function(title){
  this.title = title;
 },
 getTitle: function(){
  return this.title;
 },
 setAuthor: function(author){
  this.author = author;
 },
 getAuthor: function(){
  return this.author;
 }
};

使用这种方法实现的封装,虽然实现了取值器与赋值器以保护私有属性。但是在实际使用中,私有属性依然可以从外部访问,所以从根本上讲,没有实现封装。

2. 用命名规范进行区别

var Book = function(isbn,title,author){
 this.setIsbn(isbn);
 this.setTitle(title);
 this.setAuthor(author);
};

Book.prototype = {
 setIsbn: function(isbn){
  this._isbn = isbn;
 },
 getIsbn: function(){
  return this._isbn;
 },
 setTitle: function(title){
  this._title = title;
 },
 getTitle: function(){
  return this._title;
 },
 setAuthor: function(author){
  this._author = author;
 },
 getAuthor: function(){
  return this._author;
 }
};

使用这种方法与第一种类似,区别在于使用不同的命名来保护私有属性的使用。但是,从实际应用来说其仍然没有实现封装。

3. 使用函数作用域

var Book = function(newIsbn,newTitle,newAuthor){
 var isbn,title,author;

 this.setIsbn=function(newIsbn){
  isbn = newIsbn;
 };
 this.getIsbn=function(){
  return isbn;
 };
 this.setTitle=function(newTitle){
  title = newTitle;
 };
 this.getTitle=function(){
  return title;
 };
 this.setIsbn=function(newAuthor){
  author = newAuthor;
 };
 this.getIsbn=function(){
  return author;
 };
}

由于在JavaScript的函数中声明的变量是有作用域的,所以使用这种方法可以避免在外部直接访问私有属性。基本达到封装所要求的内容。

这里要注意的是,我们在函数的内部,可以使用this.XXX以及var来声明变量。区别是使用this.XXX声明的变量在外部是可以访问的。使用var声明的变量,由于受到函数作用域的保护,在函数的外部是无法直接访问的。

4. 使用函数作用域的变形

var Book = (function(){
 // ...其他静态方法

 return function(newIsbn,newTitle,newAuthor){
  var isbn,title,author;

  this.setIsbn=function(newIsbn){
   isbn = newIsbn;
  };
  this.getIsbn=function(){
   return isbn;
  };
  this.setTitle=function(newTitle){
   title = newTitle;
  };
  this.getTitle=function(){
   return title;
  };
  this.setIsbn=function(newAuthor){
   author = newAuthor;
  };
  this.getIsbn=function(){
   return author;
  };
 };
})();

这种方法是直接返回一个构造器的执行。且这里的构造器是一个内嵌函数。

这种方法的优点是“在内存中只会存在一份。因为其他静态方法被声明在构造器之外,所以它们不是特权方法。”

判断一个方法是否应该被设计为静态方法的原则是“这个方法是否会访问私有属性”。如果它不需要,那么将其设计为静态方法会更有效率,因为它只会被创建一份。

常量
我们可以使用“只有取值器,没有赋值器”的方式来实现常量。

// 1.
var Book = function(){
 var constants = ["key1": "1","key2": "2","key3": "3"];

 this.getConstant = function(key){
  return constants[key];
 };
};

Book.getConstant("key1");

// 2.
var Book = (function(){
 var constants = ["key1": "1","key2": "2","key3": "3"];

 var con = function(){};
 con.getConstant = function(name){
  return constants[name];
 };

 return con;
})();

Book.getConstant("key1");

利弊
1、利处

封装保护了内部数据的完整性;
封装使对象的重构更轻松;
弱化模块间的耦合,提高对象的可重用性;
有助于避免命名空间冲突;
……
2、弊处

私用方法很难测试;
必须与复杂的作用域链打交道,使错误调度更困难;
容易形成过度封装;
JavaScript并不原生支持封装,所以在JavaScript中实现封装存在复杂性的问题;

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
关于js中window.location.href,location.href,parent.location.href,top.location.href的用法与区别
Oct 18 Javascript
Node.js生成HttpStatusCode辅助类发布到npm
Apr 09 Javascript
js页面跳转的问题(跳转到父页面、最外层页面、本页面)
Aug 14 Javascript
jquery遍历checkbox的注意事项说明
Feb 21 Javascript
js操作输入框提示信息且响应鼠标事件
Mar 25 Javascript
node.js操作mongoDB数据库示例分享
Nov 26 Javascript
js实现点击图片自动提交action的简单方法
Oct 16 Javascript
JS比较两个数值的大小实例
Nov 25 Javascript
基于JavaScript实现自动更新倒计时效果
Dec 19 Javascript
three.js加载obj模型的实例代码
Nov 10 Javascript
详解vue项目打包步骤
Mar 29 Javascript
vue实现同时设置多个倒计时
May 20 Vue.js
学习Javascript面向对象编程之封装
Feb 23 #Javascript
javascript每日必学之封装
Feb 23 #Javascript
jQuery常用知识点总结以及平时封装常用函数
Feb 23 #Javascript
使用Javascript实现选择下拉菜单互移并排序
Feb 23 #Javascript
jQuery拖拽排序插件制作拖拽排序效果(附源码下载)
Feb 23 #Javascript
JavaScript tab选项卡插件实例代码
Feb 23 #Javascript
Javascript技术栈中的四种依赖注入详解
Feb 23 #Javascript
You might like
基于mysql的论坛(7)
2006/10/09 PHP
解析如何用php screw加密php源代码
2013/06/20 PHP
基于PHP给大家讲解防刷票的一些技巧
2015/11/18 PHP
轻松掌握php设计模式之访问者模式
2016/09/23 PHP
CodeIgniter框架常见用法工作总结
2017/03/16 PHP
thinkPHP中U方法加密传递参数功能示例
2018/05/29 PHP
jQuery ui1.7 dialog只能弹出一次问题
2009/08/27 Javascript
js对象关系图 方便dom操作
2012/03/18 Javascript
各种常用的JS函数整理
2013/10/25 Javascript
JS关键字球状旋转效果的实例代码
2013/11/29 Javascript
js实现当鼠标移到表格上时显示这一格全部内容的代码
2016/06/12 Javascript
jQuery实现的多张图无缝滚动效果【测试可用】
2016/09/12 Javascript
微信小程序前端源码逻辑和工作流
2016/09/25 Javascript
浅谈jQuery添加的HTML,JS失效的问题
2016/10/05 Javascript
最基础的vue.js双向绑定操作
2017/08/23 Javascript
bootstrap模态框嵌套、tabindex属性、去除阴影的示例代码
2017/10/17 Javascript
jquery select插件异步实时搜索实例代码
2017/10/20 jQuery
详解如何在微信小程序开发中正确的使用vant ui组件
2018/09/13 Javascript
React如何解决fetch跨域请求时session失效问题
2018/11/02 Javascript
p5.js码绘“跳动的小正方形”的实现代码
2019/10/22 Javascript
详细分析React 表单与事件
2020/07/08 Javascript
vue内置组件keep-alive事件动态缓存实例
2020/10/30 Javascript
python实现无证书加密解密实例
2014/10/27 Python
Python判断操作系统类型代码分享
2014/11/22 Python
python采集百度百科的方法
2015/06/05 Python
在类Unix系统上开始Python3编程入门
2015/08/20 Python
Django 使用logging打印日志的实例
2018/04/28 Python
python绘制多个曲线的折线图
2020/03/23 Python
详解numpy1.19.4与python3.9版本冲突解决
2020/12/15 Python
使用HTML5的链接预取功能(link prefetching)给网站提速
2012/12/13 HTML / CSS
意大利中国电子产品购物网站:Geekmall.com
2019/09/30 全球购物
python re模块和正则表达式
2021/03/24 Python
法律专业实习鉴定
2013/12/22 职场文书
银行青年文明号事迹材料
2014/05/31 职场文书
入党积极分子批评与自我批评思想汇报
2014/09/14 职场文书
保护环境建议书作文500字
2015/09/14 职场文书