理解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 相关文章推荐
javascript 写的一个简单的timer
Jul 30 Javascript
extjs grid设置某列背景颜色和字体颜色的方法
Sep 03 Javascript
js处理php输出时间戳对不上号的解决方法
Jun 20 Javascript
javascript实现unicode与ASCII相互转换的方法
Dec 10 Javascript
Bootstrap 源代码分析(未完待续)
Aug 17 Javascript
Javascript基于jQuery UI实现选中区域拖拽效果
Nov 25 Javascript
Bootstrap模态窗口源码解析
Feb 08 Javascript
js实现一键复制功能
Mar 16 Javascript
对于Javascript 执行上下文的全面了解
Sep 05 Javascript
深入理解Vue router的部分高级用法
Aug 15 Javascript
trackingjs+websocket+百度人脸识别API实现人脸签到
Nov 26 Javascript
Vue.js中的extend绑定节点并显示的方法
Jun 20 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
《一拳超人》埼玉一拳下去,他们存在了800年毫无意义!
2020/03/02 日漫
PHP获取数组中重复最多的元素的实现方法
2014/11/11 PHP
PHP基于phpqrcode生成带LOGO图像的二维码实例
2015/07/10 PHP
Underscore.js 的模板功能介绍与应用
2012/12/24 Javascript
js调用打印机打印网页字体总是缩小一号的解决方法
2014/01/24 Javascript
浅谈javascript事件取消和阻止冒泡
2015/05/26 Javascript
理解JavaScript中Promise的使用
2016/01/18 Javascript
全面详细的jQuery常见开发技巧手册
2016/02/21 Javascript
javascript基本语法
2016/05/31 Javascript
Three.js学习之几何形状
2016/08/01 Javascript
使用JS实现图片展示瀑布流效果的实例代码
2016/09/12 Javascript
bootstrapValidator bootstrap-select验证不可用的解决办法
2017/01/11 Javascript
原生js编写2048小游戏
2017/03/17 Javascript
js排序与重组的实例讲解
2017/08/28 Javascript
node app 打包工具pkg的具体使用
2019/01/17 Javascript
通过实例解析jQ Ajax操作相关原理
2020/09/23 Javascript
在elementui中Notification组件添加点击事件实例
2020/11/11 Javascript
python读取视频流提取视频帧的两种方法
2020/10/22 Python
python得到单词模式的示例
2018/10/15 Python
Python自动化之数据驱动让你的脚本简洁10倍【推荐】
2019/06/04 Python
对Django中static(静态)文件详解以及{% static %}标签的使用方法
2019/07/28 Python
原生python实现knn分类算法
2019/10/24 Python
python matplotlib 绘图 和 dpi对应关系详解
2020/03/14 Python
CSS3 分类菜单效果
2019/05/27 HTML / CSS
CSS3 按钮边框动画的实现
2020/11/12 HTML / CSS
使用HTML5进行SVG矢量图形绘制的入门教程
2016/02/19 HTML / CSS
美国床垫连锁店:Mattress Firm
2021/02/13 全球购物
师范生实习自我鉴定
2013/11/01 职场文书
优秀研究生自我鉴定
2013/12/04 职场文书
中学家长会邀请函
2014/01/17 职场文书
2014法院四风问题对照检查材料思想汇报
2014/10/04 职场文书
小学教师个人总结
2015/02/05 职场文书
党支部审查意见
2015/06/02 职场文书
赡养老人协议书范本
2015/08/06 职场文书
Android Flutter实现图片滑动切换效果
2022/04/07 Java/Android
Moment的feature导致线上bug解决分析
2022/09/23 Javascript