理解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添加输出窗口的代码
Feb 07 Javascript
jQuery getJSON 处理json数据的代码
Jul 26 Javascript
jQuery EasyUI API 中文文档 - Parser 解析器
Sep 29 Javascript
javascript确认框的三种使用方法
Dec 17 Javascript
js实现div闪烁原理及实现代码
Jun 24 Javascript
JavaScript中的Primitive对象封装介绍
Dec 31 Javascript
javascript实现unicode与ASCII相互转换的方法
Dec 10 Javascript
浅析javascript函数表达式
Feb 10 Javascript
解析JavaScript数组方法reduce
Dec 12 Javascript
angular实现form验证实例代码
Jan 17 Javascript
Bootstrap Table 在指定列中添加下拉框控件并获取所选值
Jul 31 Javascript
vue自定义指令和动态路由实现权限控制
Aug 28 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中函数的形参与实参的问题说明
2010/09/01 PHP
php通过session防url攻击方法
2014/12/10 PHP
php运行报错Call to undefined function curl_init()的最新解决方法
2016/11/20 PHP
Laravel5.1框架路由分组用法实例分析
2020/01/04 PHP
jquery 图片 上一张 下一张 链接效果(续篇)
2010/04/20 Javascript
jquery validate 自定义验证方法介绍 日期验证
2014/02/27 Javascript
jquery实现华丽的可折角广告代码
2015/09/02 Javascript
基于Javascript实现返回顶部按钮
2016/02/29 Javascript
第六章之辅组类与响应式工具
2016/04/25 Javascript
详解Sea.js中Module.exports和exports的区别
2017/02/12 Javascript
jquery一键控制checkbox全选、反选或全不选
2017/10/16 jQuery
Three.js加载外部模型的教程详解
2017/11/10 Javascript
js实现一个简易计算器
2020/03/30 Javascript
[49:54]Ti4 循环赛第三日 LGD vs Titan
2014/07/12 DOTA
简单掌握Python中glob模块查找文件路径的用法
2016/07/05 Python
python 剪切移动文件的实现代码
2018/08/02 Python
python linecache 处理固定格式文本数据的方法
2019/01/08 Python
python3 字符串/列表/元组(str/list/tuple)相互转换方法及join()函数的使用
2019/04/03 Python
利用python实现短信和电话提醒功能的例子
2019/08/08 Python
通过实例简单了解Python中yield的作用
2019/12/11 Python
Jimmy Choo美国官网:周仰杰鞋子品牌
2018/06/08 全球购物
从当地商店送来的杂货:Instacart
2018/08/19 全球购物
全球立体声:World Wide Stereo
2018/09/29 全球购物
eBay加拿大站:eBay.ca
2019/06/20 全球购物
P D PAOLA法国官网:西班牙著名的珠宝首饰品牌
2020/02/15 全球购物
JSF的标签库有哪些
2012/04/27 面试题
怎么写好自荐信
2013/10/30 职场文书
租房协议书怎么写
2014/04/10 职场文书
2014年计划生育工作总结
2014/11/14 职场文书
采购部年度工作总结
2015/08/13 职场文书
初中思想品德教学反思
2016/02/24 职场文书
感恩信:写给爸爸妈妈的一封感谢信
2019/09/12 职场文书
2019年作为一名实习生的述职报告
2019/09/29 职场文书
导游词之包公祠
2019/11/25 职场文书
一文搞懂redux在react中的初步用法
2021/06/09 Javascript
TV动画《间谍过家家》公开PV
2022/03/20 日漫