封装可以被定义为对对象的内部数据表现形式和实现细节进行隐藏。通过封装可以强制实施信息隐藏。

在JavaScript中,并没有显示的声明私有成员的关键字等。所以要想实现封装/信息隐藏就需要从另外的思路出发。我们可以使用闭包的概念来创建只允许从对象内部访问的方法和属性,来达到封装的要求。

基本方式
一般来说,我们学用的有三种方法来达到封装的目的。

使用this.XXX来声明一个变量,然后再声明getXXX、setXXX等取值、赋值的方法。
使用this._XXX来声明一个变量,然后再声明getXXX、setXXX等取值、赋值的方法。
利用“函数作用域”这一个概念来做。
1. 门户大开型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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. 用命名规范进行区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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. 使用函数作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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. 使用函数作用域的变形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 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封装的更多相关文章

  1. 深入理解Javascript封装DOMContentLoaded事件

    最近在写一个Javascript的框架,刚把DOMContentLoaded事件封装好,略带小兴奋,把开发过程中遇到的原理和兼容性问题做篇笔记,省的忘记到处找. 我们在写js代码的时候,一般都会添加w ...

  2. 深入理解javascript函数系列第一篇——函数概述

    × 目录 [1]定义 [2]返回值 [3]调用 前面的话 函数对任何一门语言来说都是一个核心的概念.通过函数可以封装任意多条语句,而且可以在任何地方.任何时候调用执行.在javascript里,函数即 ...

  3. 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点

    深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 2011-12-28 23:00 by 汤姆大叔, 139489 阅读, 119 评论, 收藏, 编辑 才华横溢的 ...

  4. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  5. 【干货理解】理解javascript中实现MVC的原理

    理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...

  6. 深入理解Javascript面向对象编程

    深入理解Javascript面向对象编程 阅读目录 一:理解构造函数原型(prototype)机制 二:理解原型域链的概念 三:理解原型继承机制 四:理解使用类继承(继承的更好的方案) 五:建议使用封 ...

  7. 理解javascript中的策略模式

    理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 使用策略模式的优点如下: 优点:1. 策略模式利用组合,委托等技术和思想,有效 ...

  8. 理解Javascript的动态语言特性

    原文:理解Javascript的动态语言特性 理解Javascript的动态语言特性 Javascript是一种解释性语言,而并非编译性,它不能编译成二进制文件. 理解动态执行与闭包的概念 动态执行: ...

  9. 深入理解JavaScript系列(33):设计模式之策略模式(转)

    介绍 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户. 正文 在理解策略模式之前,我们先来一个例子,一般情况下,如果我们要做数据合法性验证,很 ...

随机推荐

  1. HDU 5442 Favorite Donut(暴力 or 后缀数组 or 最大表示法)

    http://acm.hdu.edu.cn/showproblem.php?pid=5442 题意:给出一串字符串,它是循环的,现在要选定一个起点,使得该字符串字典序最大(顺时针和逆时针均可),如果有 ...

  2. HDU 5791 Two(LCS求公共子序列个数)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5791 题意: 给出两个序列,求这两个序列的公共子序列的总个数. 思路: 和LCS差不多,dp[i][ ...

  3. 【Java】【泛型】

    泛型的优点使⽤泛型有下⾯⼏个优点:1.类型安全2.向后兼容3.层次清晰4.性能较⾼,⽤GJ(泛型JAVA)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进⼀步优化提 ...

  4. Codeforces 781D Axel and Marston in Bitland

    题目链接:http://codeforces.com/contest/781/problem/D ${F[i][j][k][0,1]}$表示是否存在从${i-->j}$的路径走了${2^{k}} ...

  5. SNMOJ 31

    考虑将给入的$A$数组差分,得到差分数组$C$ 每一次操作相当于把差分数组的每一位${+1}$,其中一个位置上${-n+1}$. 我们可以直接算出要进行多少次操作:${T=\frac{\sum A[i ...

  6. selenium 指定滚动到某个元素

    from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from se ...

  7. CentOS6.5下卸载自带的MySQL数据库安装MySQL5.6

    1)查看CentOS自带的mysql 输入 rpm -qa | grep mysql mysql-libs-5.1.71-1.el6.x86_64 2)将其自带的mysql版本全部卸载(非常重要,如不 ...

  8. [osg]osg窗口显示和单屏幕显示

    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile("cow.osg"); osg::ref_ptr&l ...

  9. ABP捕捉异常错误代码

    在服务层或者CORE层  随便哪里都可以  创建一个捕捉异常的文件夹  里面写一个LonsidException类 继承后面的接口  然后重写继承的方法  这样在ABP项目运行阶段  无论在哪里出现异 ...

  10. typeScript入门基础 (1)

    1.ts是js的超集,可使用es5,es6的代码 2. ts的安装与编译: a.  首先需要Node.js环境 .  相信都有,略过. 不会的请百度,或者留言. b.  npm  install  - ...