理解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 相关文章推荐
JQUBAR1.1 jQuery 柱状图插件发布
Nov 28 Javascript
jquery实现非叠加式的搜索框提示效果
Jan 07 Javascript
html文档中的location对象属性理解及常见的用法
Aug 13 Javascript
详解JavaScript中void语句的使用
Jun 04 Javascript
jQuery position() 函数详解以及jQuery中position函数的应用
Dec 14 Javascript
JS中创建函数的三种方式及区别
Mar 13 Javascript
通过修改360抢票的刷新频率和突破8车次限制实现方法
Jan 04 Javascript
JS检测window.open打开的窗口是否关闭
Jun 25 Javascript
Vue中父子组件通讯之todolist组件功能开发
May 21 Javascript
jQuery实现侧边栏隐藏与显示的方法详解
Dec 22 jQuery
Vue2.0 实现页面缓存和不缓存的方式
Nov 12 Javascript
基于JavaScript实现控制下拉列表
May 08 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中flush()、ob_flush()、ob_end_flush()的区别介绍
2013/02/17 PHP
在次封装easyui-Dialog插件实现代码
2010/11/14 Javascript
js 字符串转化成数字的代码
2011/06/29 Javascript
jQuery1.6 类型判断实现代码
2011/09/01 Javascript
用Jquery实现滚动新闻
2014/02/12 Javascript
谷歌浏览器调试JavaScript小技巧
2014/12/29 Javascript
js限制文本框只能输入整数或者带小数点的数字
2015/04/27 Javascript
javascript单页面手势滑屏切换原理详解
2016/03/21 Javascript
JS正则替换掉小括号及内容的方法
2016/11/29 Javascript
微信小程序商品详情页的底部弹出框效果
2020/11/16 Javascript
jquery.onoff实现简单的开关按钮功能(推荐)
2018/05/24 jQuery
小程序云开发实战小结
2018/10/25 Javascript
微信小程序如何修改本地缓存key中单个数据的详解
2019/04/26 Javascript
通过说明与示例了解js五种设计模式
2019/06/17 Javascript
js实现移动端轮播图滑动切换
2020/12/21 Javascript
[00:10]DOTA2 TI9勇士令状明日上线
2019/05/07 DOTA
Python将xml和xsl转换为html的方法
2015/03/10 Python
使用Python中的线程进行网络编程的入门教程
2015/04/15 Python
在Python中使用HTMLParser解析HTML的教程
2015/04/29 Python
简单的Apache+FastCGI+Django配置指南
2015/07/22 Python
基于python实现的抓取腾讯视频所有电影的爬虫
2016/04/22 Python
使用python实现knn算法
2017/12/20 Python
python之文件读取一行一行的方法
2018/07/12 Python
Python selenium文件上传下载功能代码实例
2020/04/13 Python
如何在sublime编辑器中安装python
2020/05/20 Python
Python如何实现FTP功能
2020/05/28 Python
深入浅析css3 中display box使用方法
2015/11/25 HTML / CSS
TobyDeals美国:在电子产品上获得最好的优惠和折扣
2019/08/11 全球购物
Linux上比较文件的命令都有哪些
2013/09/28 面试题
期末考试动员演讲稿
2014/01/10 职场文书
建筑工程质量通病防治方案
2014/06/08 职场文书
圣诞晚会主持词
2015/07/01 职场文书
请假条应该怎么写?
2019/06/24 职场文书
MySQL入门命令之函数-单行函数-流程控制函数
2021/04/05 MySQL
JavaScript实例 ODO List分析
2022/01/22 Javascript
Android中View.post和Handler.post的关系
2022/06/05 Java/Android