理解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 this 深入理解
Jul 30 Javascript
js 跳出页面的frameset框架示例介绍
Dec 23 Javascript
谈一谈javascript闭包
Jan 28 Javascript
JS+CSS3模拟溢出滚动效果
Aug 12 Javascript
带你了解session和cookie作用原理区别和用法
Aug 14 Javascript
angular2 ng2-file-upload上传示例代码
Aug 23 Javascript
JS中appendChild追加子节点无效的解决方法
Oct 14 Javascript
微信小程序使用二次贝塞尔曲线画波浪
Dec 25 Javascript
JQuery常见节点操作实例分析
May 15 jQuery
微信小游戏中three.js离屏画布的示例代码
Oct 12 Javascript
使用JS实现鼠标放上图片进行放大离开实现缩小功能
Jan 27 Javascript
AJAX实现省市县三级联动效果
Oct 16 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
Discuz板块横排显示图片的实现方法
2007/05/28 PHP
php+mysql分页代码详解
2008/03/27 PHP
php+mysql 实现身份验证代码
2010/03/24 PHP
PHP之sprintf函数用法详解
2014/11/12 PHP
两个php日期控制类实例
2014/12/09 PHP
PHP微信开发之二维码生成类
2015/06/26 PHP
分享一个漂亮的php验证码类
2016/09/29 PHP
yii通过小物件生成view的方法
2016/10/08 PHP
PHP调用API接口实现天气查询功能的示例
2017/09/21 PHP
ThinkPHP 5.1 跨域配置方法
2019/10/11 PHP
table insertRow、deleteRow定义和用法总结
2014/05/14 Javascript
jQuery学习笔记之jQuery构建函数的7种方法
2014/06/03 Javascript
每天一篇javascript学习小结(Boolean对象)
2015/11/12 Javascript
javascript瀑布流式图片懒加载实例解析与优化
2016/02/23 Javascript
Node.js通过身份证号验证年龄、出生日期与性别方法示例
2017/03/09 Javascript
[js高手之路]设计模式系列课程-发布者,订阅者重构购物车的实例
2017/08/29 Javascript
4个顶级开源JavaScript图表库
2018/09/29 Javascript
解决Vue+Electron下Vuex的Dispatch没有效果问题
2019/05/20 Javascript
layUI的验证码功能及校验实例
2019/10/25 Javascript
JQuery插件tablesorter表格排序实现过程解析
2020/05/28 jQuery
Python异常学习笔记
2015/02/03 Python
Python对文件操作知识汇总
2016/05/15 Python
python 上下文管理器使用方法小结
2017/10/10 Python
selenium python浏览器多窗口处理代码示例
2018/01/15 Python
Python命令行解析模块详解
2018/02/01 Python
Python进阶之全面解读高级特性之切片
2019/02/19 Python
python实现将range()函数生成的数字存储在一个列表中
2020/04/02 Python
Python+OpenCV图像处理——打印图片属性、设置存储路径、调用摄像头
2020/10/22 Python
中国综合网上购物商城:苏宁易购
2016/08/09 全球购物
大学生思想汇报范文
2013/12/31 职场文书
关于毕业的中学校园广播稿
2014/01/26 职场文书
乡镇交通安全实施方案
2014/03/29 职场文书
解除合同协议书
2014/04/17 职场文书
安全生产专项整治方案
2014/05/06 职场文书
小数乘法教学反思
2016/02/22 职场文书
市场营销计划书
2019/04/24 职场文书