第三章

创建对象的基本模式

方法一:门户大开型
var Book = function(isbn, title, author) {
  if(isbn == undefined ) throw new Error ('Book constructor requires an isbn.');
  this.isbn = isbn;
  this.title = title || 'No title specified';
  this.author = author || 'No author specified';
}
 
Book.prototype.display = function () {
        ...
};
特点:所有属性都是公开的,并且没有有效的验证数据的有效性

方法二:加强对属性的检测
var Book = function(isbn, title, author) {
  if( !this.checkIsbn(isbn)) throw new Error( 'Book: Invalid ISBN.');
  this.isbn = isbn;
  this.title = title || 'No title specified';
  this.author = author || 'No author specified';
}
 
Book.prototype = {
  checkIsbn : function (isbn) {
    if(isbn == undefined || typeof isbn != 'string') {
      return false ;
    }
 
    isbn = isbn.replace(/-/ . ''); // Remove dashes.
    if(isbn.length != 10 && isbn.length != 13) {
      return false ;
    }
 
    var sum = 0;
    if(isbn.length === 10) { // 10 digit ISBN.
      If( !isbn.match(\^\ d{9 }\)) { // Ensure characters 1 through 9 are digits.
        return false ;
      }
 
      for(var i = 0; i < 9; i ++) {
        sum += isbn.charAt(i) * (10 - i);
      }
      var checksum = sum % 11;
      if(checksum === 10) checksum = 'X' ;
      if(isbn.charAt(9 ) != checksum) {
        return false ;
      }
    }
    else { // 13 digit ISBN.
      if(! isbn.match(\ ^\d{12} \)) { // Ensure characters 1 through 12 are digits.
        return false ;
      }
 
      for(var i = 0; i < 12; i ++) {
        sum += isbn.charAt(i) * ((i % 2 === 0) ? 1 : 3);
      }
      var checksum = sum % 10;
      if(isbn.charAt(12 ) != checksum) {
        return false ;
      }
    }
 
    return true ; // All tests passed.
  },
 
  display: function() {
    ...
  }
};
特点:在Book.prototype上添加了一个checkIsbn函数,可以在实例化的时候检查数据的有效性
缺点:还没有解决属性暴露在外面的问题

方法三:添加取值器和赋值器
var Book = function(isbn, title, author) { // implements Publication
  this.setIsbn(isbn);
  this.setTitle(title);
  this.setAuthor(author);
}
 
Book.prototype = {
  checkIsbn : function (isbn) {
    ...
  },
  getIsbn: function() {
    return this .isbn;
  },
  setIsbn: function(isbn) {
    if(! this.checkIsbn(isbn)) throw new Error('Book: Invalid ISBN.' );
    this.isbn = isbn;
  },
 
  getTitle : function () {
    return this .title;
  },
  setTitle : function (title) {
    this.title = title || 'No title specified';
  },
 
  getAuthor : function () {
    return this .author;
  },
  setAuthor : function (author) {
    this.author = author || 'No author specified';
  },
 
  display: function() {
    ...
  }
};
特点:上面方法的一个改进,通过赋值器验证数据的有效性
缺点:赋值器和取值器添加了额外的代码,而且属性还是暴露在外面

方法四:用命名规范区别私用成员
var Book = function(isbn, title, author) { // implements Publication
  this.setIsbn(isbn);
  this.setTitle(title);
  this.setAuthor(author);
}
 
Book.prototype = {
  _checkIsbn : function (isbn) {
    ...
  },
  getIsbn: function() {
    return this ._isbn;
  },
  setIsbn: function(isbn) {
    if(! this._checkIsbn(isbn)) throw new Error('Book: Invalid ISBN.' );
    this._isbn = isbn;
  },
 
  getTitle : function () {
    return this ._title;
  },
  setTitle : function (title) {
    this._title = title || 'No title specified';
  },
 
  getAuthor : function () {
    return this ._author;
  },
  setAuthor : function (author) {
    this._author = author || 'No author specified';
  },
 
  display: function() {
    ...
  }
};
特点:其实也就是把属性的名称下面加了一个下划线"_"。在属性名前加一个下划线是说明这是私有变量的一种约定,使用的人就可以清楚不应该修改这个属性。
缺点:这只是一种约定,可以让别人不误用,但是如果别人有意要修改这私有属性,也是可以的。

方法五:用闭包实现私有成员
var Book = function(newIsbn, newTitle, newAuthor) { // implements Publication
 
  // Private attributes.
  var isbn, title, author;
 
  // Private method.
  function checkIsbn(isbn) {
    ...
  } 
 
  // Privileged methods.
  this.getIsbn = function () {
    return isbn;
  };
  this.setIsbn = function (newIsbn) {
    if(! checkIsbn(newIsbn)) throw new Error ('Book: Invalid ISBN.');
    isbn = newIsbn;
  };
 
  this.getTitle = function () {
    return title;
  };
  this.setTitle = function (newTitle) {
    title = newTitle || 'No title specified';
  };
 
  this.getAuthor = function () {
    return author;
  };
  this.setAuthor = function (newAuthor) {
    author = newAuthor || 'No author specified';
  };
 
  // Constructor code.
  this.setIsbn(newIsbn);
  this.setTitle(newTitle);
  this.setAuthor(newAuthor);
};
 
// Public, non-privileged methods.
Book.prototype = {
  display: function() {
    ...
  }
};
特点:私有变量用var声明而不用this赋给对象,使对象不能直接操作私有变量。此外,用this.method这样的方法定义特权方法(赋值器等),使用于可以通过特权方法操作私有变量,公共方法就定义在Book.prototype中。
缺点:特权方法的增加会耗费更多的内存,不像第一种方法一样把所有方法都放在prototype里面。并且以后的子类都不能访问这这样定义的私有方法

方法五:静态方法和属性
var Book = (function() {
 
  // Private static attributes.
  var numOfBooks = 0 ;
 
  // Private static method.
  function checkIsbn(isbn) {
    ...
  }   
 
  // Return the constructor.
  return function(newIsbn, newTitle, newAuthor) { // implements Publication
 
    // Private attributes.
    var isbn, title, author;
 
    // Privileged methods.
    this.getIsbn = function() {
      return isbn;
    };
    this.setIsbn = function(newIsbn) {
      if(! checkIsbn(newIsbn)) throw new Error ('Book: Invalid ISBN.');
      isbn = newIsbn;
    };
 
    this.getTitle = function() {
      return title;
    };
    this.setTitle = function(newTitle) {
      title = newTitle || 'No title specified';
    };
 
    this.getAuthor = function() {
      return author;
    };
    this.setAuthor = function(newAuthor) {
      author = newAuthor || 'No author specified';
    };
 
    // Constructor code.
    numOfBooks ++; // Keep track of how many Books have been instantiated
                  // with the private static attribute.
    if(numOfBooks > 50) throw new Error( 'Book: Only 50 instances of Book can be '
        + 'created.' );
 
    this.setIsbn(newIsbn);
    this.setTitle(newTitle);
    this.setAuthor(newAuthor);
  }
})();
 
// Public static method.
Book.convertToTitleCase = function (inputString) {
  ...
};
 
// Public, non-privileged methods.
Book.prototype = {
  display: function() {
    ...
  }
};
 
特点:这种方法最大一个特点就是构造函数是通过立即调用函数返回出来的,这样外层的这个立即调用函数就形成了一个闭包,在里面我们就可以声明一些静态私有的变量或者方法了。

方法六:常量
var Class = (function() {
 
  // Private static attributes.
  var constants = {
    UPPER_BOUND : 100 ,
    LOWER_BOUND : -100
  }
 
// Constructor
var ctor = function(constructorArgument) {
     ...
};
 
  // Privileged static method.
  ctor.getConstant(name) {
    return constants[name];
  }
 
  ...
 
  // Return the constructor.
  return ctor;
})();
 
 
/* Usage. */
 
Class.getConstant( 'UPPER_BOUND');
特点:同样上面的那种方法,不同的是只设置一个取值器,不设置赋值器,就可以模仿常量了。

小结:上面所有方法都是返回值都是构造函数来的,如果我们不需要构造函数,就可以利用单体模式,后面章节会说。此外,封装的最好用处就是防止别人修改你的数据,最大的缺点就是麻烦~

一个综合例子:

<html>

<body>
<script>
var Student = (function(){
var _count = ;//私有静态变量
var constants = {//常量
MAX_NUM :
}; function Student(name, age) {
var _name;//私有变量
var _age;//私有变量 var checkAge = function(age) {//私有方法
if(typeof(age) != 'number') {
return false;
} else {
return true;
}
}; this.setName = function(name) {//特权方法
_name = name;
}; this.setAge = function(age) {//特权方法
if(!checkAge(age)) throw new Error("age should be number");
_age = age;
}; this.getName = function() {//特权方法
return _name;
}; this.getAge = function() {//特权方法
return _age;
}; this.setName(name);
this.setAge(age);
_count++;
} Student.getConstant = function(name) {//公共静态方法
return constants[name];
}; Student.getCount = function() {//公共静态方法
return _count;
}; Student.prototype.showName = function() {//公共非特权方法
alert(this.getName());
}; Student.prototype.showAge = function() {//公共非特权方法
alert(this.getAge());
}; return Student;
})(); //使用
var Mark = new Student('Mark', );
var Sally = new Student('Sally', );
</script></body>

 

《JavaScript设计模式》笔记之第三章:封装和信息隐藏的更多相关文章

  1. Javascript设计模式笔记

    Javascript是越来越厉害了,一统前后端开发.于是最近把设计模式又看了一遍,顺便做了个笔记,以方便自己和他人共同学习. 笔记连载详见:http://www.meteorcn.net/wordpr ...

  2. JavaScript设计模式——前奏(封装和信息隐藏)

    前面一篇讲了js设计模式的前奏,包括接口的讲解.. 三:封装和信息隐藏: 信息隐藏用来进行解耦,定义一些私有的数据和方法. 封装是用来实现信息隐藏的技术,通过闭包实现私有数据的定义和使用. 接口在这其 ...

  3. [书籍翻译] 《JavaScript并发编程》第三章 使用Promises实现同步

    本文是我翻译<JavaScript Concurrency>书籍的第三章 使用Promises实现同步,该书主要以Promises.Generator.Web workers等技术来讲解J ...

  4. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第三章:变换

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第三章:变换 学习目标 理解如何用矩阵表示线性变换和仿射变换: 学习在 ...

  5. 《JAVASCRIPT高级程序设计》第三章

    <JAVASCRIPT高级程序设计>第三章主要讲述了这门语言的基础概念,内容多而浅,通过思维导图可以帮助我们很好的理清脉络. js函数使用function关键字来声明,以下是一个简单的例子 ...

  6. javascript面向对象精要第三章对象整理精要

    什么是对象的数据属性?什么是对象的访问器属性?[put]方法是默认创建数据属性的,访 问器属性不包含值而是定义了一个单属性被读取时调用的函数(getter)和当一个属性被写入时 调用的函数(sette ...

  7. 如何封装JS ----》JS设计模式《------ 封装与信息隐藏

    1. 封装与 信息隐藏之间的关系 实质是同一个概念的两种表达,信息隐藏式目的,二封装是借以达到目的的技术方法.封装是对象内部的数据表现形式和实现细节,要想访问封装过额对象中的数据,只有使用自己定义的操 ...

  8. JS设计模式——3.封装与信息隐藏

    封装.信息隐藏与接口的关系 信息隐藏是目的,封装是手段. 接口提供了一份记载着可供公共访问的方法的契约.它定义了两个对象间可以具有的关系.只要接口不变,这个关系的双方都是可以替换的. 一个理想的软件系 ...

  9. JavaScript DOM编程艺术-学习笔记(第三章、第四章)

    第三章: 1.js的对象分为三种:①用户自定义对象 ② 内建对象(js提供的对象) ③宿主对象(js寄宿的环境-浏览器,提供的对象) 2.文档是由节点组成的集合,即dom树,html元素是根元素,是唯 ...

随机推荐

  1. uva 10881 Piotr's Ants 解题报告

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&pa ...

  2. 自定义标签(客户化jsp标签)

    客户化jsp标签技术是在jsp1.1版本中才出现的,他支持用户在jsp文件中自定义标签,这样可以使jsp代码更加简单,这些可重用的标签能够处理复杂的逻辑运算和事物或定义jsp网页的输出内容和格式. 创 ...

  3. the generation has been cancelled because errors have been found by the check model

    生成物理模型出现这个错误的话,那就打开“生成物理模型”(快捷键 ctrl+shift+p) 然后找到 Detail → Option 接着讲Check mode复选框去掉.

  4. Linux中进程控制块PCB-------task_struct结构体结构

    Linux中task_struct用来控制管理进程,结构如下: struct task_struct { //说明了该进程是否可以执行,还是可中断等信息 volatile long state; // ...

  5. Snmp在Windows下的实现----WinSNMP编程原理

    在Windows 下实现SNMP协议的编程,可以采用Winsock接口,在161,162端口通过udp传送信息.在Windows 2000中,Microsoft已经封装了SNMP协议的实现,提供了一套 ...

  6. 24.如何结束返回值是void的方法

    如何结束返回值是void的方法? return;只能够出现在方法类型是void 的方法中,用来结束方法. return后面还可以跟数据,后面的数据可以是整数.字符串.false.ture.小数.主要看 ...

  7. Spring 注释标签@Resource @Autowired 和@Inject的区别

    一些spring的开发人员在使用这三个标签进行注入的时候感到困惑.我来尝试解释一下这三个注解的主要区别.事实上,这三者非常相似,只存在一些微小的差别.在稍后的文章中会进行解释. @Resource-在 ...

  8. TModJS:使用tmodjs

    ylbtech-TModJS:使用tmodjs 1.返回顶部 1. 1.安装 npm install -g tmodjs 2.配置 我的模板都放在tpl文件夹中,htmls用于存放模板页面,每一个后缀 ...

  9. weex 打包apk

    安装 weexpack weexpack create my-project    //创建项目 cd my-project cnpm install //安装依赖 npm start //运行项目 ...

  10. 写出高效优美的单片机C语言代码

    程序能跑起来并不见得你的代码就是很好的c代码了,衡量代码的好坏应该从以下几个方面来看 1,代码稳定,没有隐患. 2,执行效率高. 3,可读性高. 4,便于移植. 下面发一些我在网上看到的技巧和自己的一 ...