理解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页面不刷新时全选择,全删除(GridView)
Apr 14 Javascript
JS 参数传递的实际应用代码分析
Sep 13 Javascript
了解jQuery技巧来提高你的代码
Jan 08 Javascript
javascript下对于事件、事件流、事件触发的顺序随便说说
Jul 17 Javascript
Angularjs 实现一个幻灯片示例代码
Sep 08 Javascript
微信小程序 判断手机号的实现代码
Apr 19 Javascript
基于模板引擎Jade的应用(详解)
Dec 12 Javascript
js数组方法reduce经典用法代码分享
Jan 07 Javascript
基于angular6.0实现的一个组件懒加载功能示例
Apr 12 Javascript
vue better scroll 无法滚动的解决方法
Jun 07 Javascript
学习node.js 断言的使用详解
Mar 18 Javascript
使用Promise封装小程序wx.request的实现方法
Nov 13 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实现文件安全下载
2006/10/09 PHP
使用php+xslt在windows平台上
2006/10/09 PHP
mysql_fetch_row,mysql_fetch_array,mysql_fetch_assoc的区别
2009/04/24 PHP
PHP URL参数获取方式的四种例子
2014/02/28 PHP
php中使用key,value,current,next和prev函数遍历数组的方法
2015/03/17 PHP
php实现图片按比例截取的方法
2017/02/06 PHP
JAVASCRIPT keycode总结
2009/02/04 Javascript
JS+css 图片自动缩放自适应大小
2013/08/08 Javascript
jQuery中校验时间格式的正则表达式小结
2013/09/22 Javascript
js创建对象的区别示例介绍
2014/07/24 Javascript
javascript中几个容易混淆的概念总结
2015/04/14 Javascript
数据分析软件之FineReport教程:[5]参数界面JS(全)
2015/08/13 Javascript
浏览器复制插件zeroclipboard使用指南
2016/03/26 Javascript
javascript使用递归算法求两个数字组合功能示例
2017/01/03 Javascript
JS正则表达式判断有效数实例代码
2017/03/13 Javascript
如何使用bootstrap框架 bootstrap入门必看!
2017/04/13 Javascript
JQuery Ajax 异步操作之动态添加节点功能
2017/05/24 jQuery
Node.js实现mysql连接池使用事务自动回收连接的方法示例
2018/02/03 Javascript
javascript实现切割轮播效果
2019/11/28 Javascript
[02:35]DOTA2英雄基础教程 末日使者
2013/12/04 DOTA
[46:10]2014 DOTA2国际邀请赛中国区预选赛 CnB VS HGT
2014/05/21 DOTA
python在多玩图片上下载妹子图的实现代码
2013/08/13 Python
python实现接口并发测试脚本
2019/06/25 Python
如何利用Python开发一个简单的猜数字游戏
2019/09/22 Python
TensorFlow Saver:保存和读取模型参数.ckpt实例
2020/02/10 Python
python 中的paramiko模块简介及安装过程
2020/02/29 Python
Django框架实现在线考试系统的示例代码
2020/11/30 Python
python3列表删除大量重复元素remove()方法的问题详解
2021/01/04 Python
HTML5新控件之日期和时间选择输入的实现代码
2018/09/13 HTML / CSS
飞利浦法国官网:Philips法国
2019/07/10 全球购物
个人简历自我评价八例
2013/10/31 职场文书
市场营销毕业求职信
2014/08/07 职场文书
清明节寄语2015
2015/03/23 职场文书
2015年全国助残日活动方案
2015/05/04 职场文书
2016年七夕情人节宣传语
2015/11/25 职场文书
演讲开头怎么书写?
2019/08/06 职场文书