理解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 相关文章推荐
翻译整理的jQuery使用查询手册
Mar 07 Javascript
jquery中常用的SET和GET
Jan 13 Javascript
JavaScript高级程序设计 阅读笔记(二十一) JavaScript中的XML
Sep 14 Javascript
javaScript如何生成xmlhttp
Dec 16 Javascript
jquery鼠标停止移动事件
Dec 21 Javascript
用jQuery模拟select下拉框的简单示例代码
Jan 26 Javascript
Bootstrap每天必学之导航
Nov 26 Javascript
React Native实现简单的登录功能(推荐)
Sep 19 Javascript
学习vue.js计算属性
Dec 03 Javascript
vue+element的表格实现批量删除功能示例代码
Aug 17 Javascript
Node.js中文件系统fs模块的使用及常用接口
Mar 06 Javascript
JS实现购物车基本功能
Nov 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实现登陆验证码(类似条行码状)
2006/10/09 PHP
php教程之魔术方法的使用示例(php魔术函数)
2014/02/12 PHP
深入分析PHP引用(&)
2014/09/04 PHP
php实现模拟post请求用法实例
2015/07/11 PHP
JQuery 无废话系列教程(一) jquery入门 [推荐]
2009/06/23 Javascript
js onkeypress与onkeydown 事件区别详细说明
2012/12/13 Javascript
js添加事件的通用方法推荐
2016/05/15 Javascript
js接收并转化Java中的数组对象的方法
2016/08/11 Javascript
EasyUI 结合JS导出Excel文件的实现方法
2016/11/10 Javascript
vuejs父子组件通信的问题
2017/01/11 Javascript
Node.js读取文件内容示例
2017/03/07 Javascript
详解基于 Nuxt 的 Vue.js 服务端渲染实践
2017/10/24 Javascript
Vue 页面跳转不用router-link的实现代码
2018/04/12 Javascript
在vue项目中,将juery设置为全局变量的方法
2018/09/25 Javascript
iView框架问题整理小结
2018/10/16 Javascript
11个Javascript小技巧帮你提升代码质量(小结)
2020/12/28 Javascript
python使用装饰器和线程限制函数执行时间的方法
2015/04/18 Python
Python函数中的函数(闭包)用法实例
2016/03/15 Python
在windows系统中实现python3安装lxml
2016/03/23 Python
Python selenium 父子、兄弟、相邻节点定位方式详解
2016/09/15 Python
python3+PyQt5图形项的自定义和交互 python3实现page Designer应用程序
2020/07/20 Python
Django项目开发中cookies和session的常用操作分析
2018/07/03 Python
世界领先的以旅馆为主的在线预订平台:Hostelworld
2016/10/09 全球购物
水芝澳美国官网:H2O Plus
2016/10/15 全球购物
初级Java程序员面试题
2016/03/03 面试题
县优秀教师事迹材料
2014/01/31 职场文书
《蚕姑娘》教学反思
2014/04/15 职场文书
教师考核表个人总结
2015/02/12 职场文书
2016党员党章学习心得体会
2016/01/14 职场文书
导游经典开场白——导游词
2019/04/17 职场文书
导游词之青城山景区
2019/09/27 职场文书
判断Python中的Nonetype类型
2021/05/25 Python
Golang标准库syscall详解(什么是系统调用)
2021/05/25 Golang
《废话连篇——致新手》——chinapizza
2022/04/05 无线电
Spring Boot接口定义和全局异常统一处理
2022/04/20 Java/Android
Python 绘制多因子柱状图
2022/05/11 Python