理解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 相关文章推荐
经常用到的JavasScript事件的翻译
Apr 09 Javascript
解决Extjs 4 Panel作为Window组件的子组件时出现双重边框问题
Jan 11 Javascript
Jquery图片滚动与幻灯片的实例代码
Apr 08 Javascript
JavaScript实现动态创建CSS样式规则方案
Sep 06 Javascript
跟我学习javascript的prototype原型和原型链
Nov 18 Javascript
详解JavaScript中Hash Map映射结构的实现
May 21 Javascript
JS实现获取剪贴板内容的方法
Jun 21 Javascript
微信小程序中实现一对多发消息详解及实例代码
Feb 14 Javascript
angular使用bootstrap方法手动启动的实例代码
Jul 18 Javascript
JS使用贪心算法解决找零问题示例
Nov 27 Javascript
Vue项目服务器部署之子目录部署方法
May 12 Javascript
vue input标签通用指令校验的实现
Nov 05 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实现的博客欢迎提示功能(很特别哦)
2014/06/05 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(一)
2014/06/23 PHP
php设计模式之简单工厂模式详解
2014/09/04 PHP
apache php mysql开发环境安装教程
2016/07/28 PHP
Laravel第三方包报class not found的解决方法
2019/10/13 PHP
IE bug table元素的innerHTML
2010/01/11 Javascript
关于js注册事件的常用方法
2013/04/03 Javascript
js将字符串转成正则表达式的实现方法
2013/11/13 Javascript
jquery如何实现锚点链接之间的平滑滚动
2013/12/02 Javascript
Js表格万条数据瞬间加载实现代码
2014/02/20 Javascript
js从Cookies里面取值的简单实现
2014/06/30 Javascript
JS 打印功能代码可实现打印预览、打印设置等
2014/10/31 Javascript
在knockoutjs 上自己实现的flux(实例讲解)
2017/12/18 Javascript
微信小程序时间戳转日期的详解
2019/04/30 Javascript
vue自定义指令实现仅支持输入数字和浮点型的示例
2019/10/30 Javascript
在VUE中实现文件下载并判断状态的方法
2019/11/08 Javascript
JavaScript实现横版菜单栏
2020/03/17 Javascript
Python创建日历实例
2014/08/21 Python
Python实现CET查分的方法
2015/03/10 Python
基于python内置函数与匿名函数详解
2018/01/09 Python
python实现求特征选择的信息增益
2018/12/18 Python
对python tkinter窗口弹出置顶的方法详解
2019/06/14 Python
浅谈python 中类属性共享的问题
2019/07/02 Python
python程序 线程队列queue使用方法解析
2019/09/23 Python
Python实现图片裁剪的两种方式(Pillow和OpenCV)
2019/10/30 Python
python opencv角点检测连线功能的实现代码
2020/11/24 Python
纯CSS实现预加载动画效果
2017/09/06 HTML / CSS
Servlet如何得到服务器的信息
2015/12/22 面试题
两只小狮子教学反思
2014/02/05 职场文书
公司委托书怎么写
2014/08/02 职场文书
解放思想演讲稿
2014/09/11 职场文书
退休教师追悼词
2015/06/23 职场文书
劳动模范获奖感言
2015/07/31 职场文书
幼儿园园长新年寄语
2015/08/17 职场文书
创业计划书之o2o水果店
2019/08/30 职场文书
Nginx流量拷贝ngx_http_mirror_module模块使用方法详解
2022/04/07 Servers