理解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跨域的4种方法和原理详解
Apr 08 Javascript
javascript比较两个日期相差天数的方法
Jul 24 Javascript
JavaScript正则表达式的分组匹配详解
Feb 13 Javascript
js仿小米官网图片轮播特效
Sep 29 Javascript
javascript实现页面滚屏效果
Jan 17 Javascript
jQuery插件echarts去掉垂直网格线用法示例
Mar 03 Javascript
Angular4学习笔记之实现绑定和分包
Aug 01 Javascript
vue-cli webpack2项目打包优化分享
Feb 07 Javascript
vue结合axios与后端进行ajax交互的方法
Jul 06 Javascript
vue-cli3 项目优化之通过 node 自动生成组件模板 generate View、Component
Apr 30 Javascript
jdk1.8+vue elementui实现多级菜单功能
Sep 24 Javascript
Vue3.0 手写放大镜效果
Jul 25 Vue.js
学习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写的基于Memcache的Queue实现代码
2011/11/27 PHP
phpmyadmin3 安装配置图解教程
2012/03/29 PHP
JQUERY CHECKBOX全选,取消全选,反选方法三
2008/08/30 Javascript
用Jquery实现多级下拉框无刷新的联动
2010/12/22 Javascript
不用构造函数(Constructor)new关键字也能实现JavaScript的面向对象
2013/01/11 Javascript
JavaScript 函数惰性载入的实现及其优点介绍
2013/08/12 Javascript
javascript中match函数的用法小结
2014/02/08 Javascript
通过JS来动态的修改url,实现对url的增删查改
2014/09/01 Javascript
jQuery后代选择器用法实例
2014/12/23 Javascript
JS实现显示带倒影的图片横排居中放大展示特效实例【测试可用】
2016/08/23 Javascript
javascript中活灵活现的Array对象详解
2016/11/30 Javascript
浅析javascript中的Event事件
2016/12/09 Javascript
微信小程序 数据封装,参数传值等经验分享
2017/01/09 Javascript
利用原生JS与jQuery实现数字线性变化的动画
2017/02/24 Javascript
解决vue项目中type=”file“ change事件只执行一次的问题
2018/05/16 Javascript
AngularJS标签页tab选项卡切换功能经典实例详解
2018/05/16 Javascript
[00:12]2018DOTA2亚洲邀请赛 Sccc亮相SOLO赛,今年他又会有什么样的战绩?
2018/04/06 DOTA
Python程序设计入门(5)类的使用简介
2014/06/16 Python
Python使用正则匹配实现抓图代码分享
2015/04/02 Python
go和python变量赋值遇到的一个问题
2017/08/31 Python
Tornado高并发处理方法实例代码
2018/01/15 Python
浅谈Python实现2种文件复制的方法
2018/01/19 Python
python图书管理系统
2020/04/05 Python
Python图像的增强处理操作示例【基于ImageEnhance类】
2019/01/03 Python
python时间与Unix时间戳相互转换方法详解
2020/02/13 Python
tensorflow使用L2 regularization正则化修正overfitting过拟合方式
2020/05/22 Python
Python检测端口IP字符串是否合法
2020/06/05 Python
Python列表嵌套常见坑点及解决方案
2020/09/30 Python
Nike瑞典官方网站:Nike.com (SE)
2018/11/26 全球购物
保护母亲河倡议书
2014/04/14 职场文书
公务员试用期满考核材料
2014/05/22 职场文书
个人债务授权委托书范本
2014/10/05 职场文书
员工年终考核评语
2014/12/31 职场文书
新娘父亲婚礼致辞
2015/07/27 职场文书
大学生支教感言
2015/08/01 职场文书
检讨书范文
2019/04/16 职场文书