理解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 相关文章推荐
Mootools 1.2教程 滑动效果(Slide)
Sep 15 Javascript
javascript将浮点数转换成整数的三个方法
Jun 23 Javascript
jQuery+CSS3实现树叶飘落特效
Feb 01 Javascript
封装了jQuery的Ajax请求全局配置
Feb 05 Javascript
js控制网页前进和后退的方法
Jun 08 Javascript
javascript+HTML5自定义元素播放焦点图动画
Feb 21 Javascript
手把手教你搭建ES6的开发运行环境
Jul 11 Javascript
详解Vue项目编译后部署在非网站根目录的解决方案
Apr 26 Javascript
Vue组件全局注册实现警告框的实例详解
Jun 11 Javascript
Vue唯一可以更改vuex实例中state数据状态的属性对象Mutation的讲解
Jan 18 Javascript
js实现无缝轮播图
Mar 09 Javascript
OpenLayers3实现图层控件功能
Sep 25 Javascript
学习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
php常用Stream函数集介绍
2013/06/24 PHP
php中adodbzip类实例
2014/12/08 PHP
php递归删除目录与文件的方法
2015/01/30 PHP
深入理解PHP的远程多会话调试
2017/09/21 PHP
Nigma vs Alliance BO5 第二场2.14
2021/03/10 DOTA
Javascript的并行运算实现代码
2010/11/19 Javascript
关于jQuery UI 使用心得及技巧
2012/10/10 Javascript
浅谈JS中的bind方法与函数柯里化
2016/08/10 Javascript
canvas知识总结
2017/01/25 Javascript
关于不同页面之间实现参数传递的几种方式讨论
2017/02/13 Javascript
js实现tab切换效果
2017/02/16 Javascript
JavaScript实现QQ聊天消息展示和评论提交功能
2017/05/22 Javascript
微信小程序实现点击文字页面跳转功能【附源码下载】
2017/12/12 Javascript
基于 Vue.js 2.0 酷炫自适应背景视频登录页面实现方式
2018/01/17 Javascript
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
通过jquery.cookie.js实现记住用户名、密码登录功能
2018/06/20 jQuery
AngularJS与后端php的数据交互方法
2018/08/13 Javascript
vue3.0 CLI - 2.4 - 新组件 Forms.vue 中学习表单
2018/09/14 Javascript
关于小程序优化的一些建议(小结)
2020/12/10 Javascript
[43:49]LGD vs CHAOS 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python中使用语句导入模块或包的机制研究
2015/03/30 Python
python xlsxwriter库生成图表的应用示例
2018/03/16 Python
python3使用smtplib实现发送邮件功能
2018/05/22 Python
python3 小数位的四舍五入(用两种方法解决round 遇5不进)
2019/04/11 Python
Python 脚本的三种执行方式小结
2019/12/21 Python
浅谈Python程序的错误:变量未定义
2020/06/02 Python
详解HTML5通讯录获取指定多个人的信息
2016/12/20 HTML / CSS
英国网上超市:Ocado
2020/03/05 全球购物
简历自我评价怎么写好呢?
2014/01/04 职场文书
新闻传媒系求职信范文
2014/04/19 职场文书
责任心演讲稿
2014/05/14 职场文书
2015年化验室工作总结
2015/04/23 职场文书
张丽莉事迹观后感
2015/06/16 职场文书
校运会宣传稿大全
2015/07/23 职场文书
2016年教师寒假学习心得体会
2015/10/09 职场文书
搞笑Gif:这么白这么长的腿像极了一楼的女朋友
2022/03/21 杂记