前面一篇讲了js设计模式的前奏,包括接口的讲解..

三:封装和信息隐藏:

信息隐藏用来进行解耦,定义一些私有的数据和方法。

封装是用来实现信息隐藏的技术,通过闭包实现私有数据的定义和使用。

接口在这其中扮演的角色是:提供一份记载着可公众访问的方法的契约,它定义了两个对象间可以具有的关系。

接下来介绍一下创建对象的基本模式:

基本模式有3种:门户大开型、用下划线表示方法和属性的私用性、闭包创建私用成员

举个例子,你要创建一个Book类,别人会创建实例并使用。

    //Book(isbn,title,author)
var theHobbit = new Book('0-12-34-2654-2','the hobbit','xin');
theHobbit.display();

1.门户大开型:

所谓门户大开,即,用一个函数来做构造器,所有方法和属性都是公开的。

     //定义接口
var Publication = new Interface('Publication',['getIsbn','setIsbn','getTitle','setTitle','getAuthor','setAuthor','display']); //implements Publication
var Book = function(isbn, title, author){
this.setIsbn(isbn);
this.setTitle(title);
this.setAuthor(author);
}
Book.prototype = {
checkIsbn:function(isbn){
//.....检查isbn的格式是否规范
//.......
},
getIsbn:function(){
return this.isbn;
},
getTitle:function(){
return this.title;
},
getAuthor:function(){
return this.author;
},
setIsbn:function(isbn){
if(!this.checkIsbn(isbn)) throw new Error('Book: Invalid ISBN');
this.isbn = isbn;
},
setTitle:function(title){
this.title = title || "no title specified";
},
setAuthor:function(author){
this.author = author || "no author specified";
},
display:function(){
//..............
alert(this.getIsbn()+this.getTitle()+this.getAuthor())
}

这种方法看似很完善了,但是对于里面的属性还是可以进行修改的,isbn亦可能被赋值为一个无效值。

2.用一个函数来做构造器(用命名规范区别私用成员)

这个方法和上面的方法如出一辙,就是给私有成员加一个下划线。

就不做详细的讨论了。

3.作用域、嵌套和闭包

     //implements Publication
var Book = function(newisbn, newtitle, newauthor){
//私有成员
var isbn,title,author //私有方法
function checkIsbn(isbn){
//.....检查isbn的格式是否规范
//.......
} //特权方法
this.getIsbn(){
return isbn;
}
this.getTitle(){
return title;
}
this.getAuthor(){
return author;
}
this.setIsbn(){
if(!checkIsbn(newisbn)) throw new Error('Book: Invalid ISBN');
isbn = newisbn;
}
this.setTitle(){
title = newtitle;
}
this.setAuthor(){
author = newauthor;
} //构造
this.setIsbn(newisbn);
this.setAuthor(newauthor);
this.setTitle(newtitle);
} Book.prototype = {
display:function(){
//..............
}

这种方法存在一个问题。前面的门户大开型方法对象创建模式中,所有的方法都创建在原型对象上,因此不管生成多少对象实例,这些方法在内存中只会存在一份。而这种方法每次生成一个新的对象实例都会为每一个私用方法和特权方法生成一个新的副本。这种做法会浪费更多的内存。

这种对象创建模式不利于派生子类。(继承破坏封装.....)

最后总结一下:

私有属性和方法:函数有作用域,在函数内用var 关键字声明的变量在外部无法访问,私有属性和方法本质就是你希望在对象外部无法访问的变量。
特权属性和方法:创建属性和方法时使用的this关键字,因为这些方法定义在构造器的作用域中,所以它们可以访问到私有属性和方法;只有那些需要直接访问私有成员的方法才应该被设计为特权方法。
公有属性和方法:直接链在prototype上的属性和方法,不可以访问构造器内的私有成员,可以访问特权成员,子类会继承所有的共有方法。
公有静态属性和方法:最好的理解方式就是把它想象成一个命名空间,实际上相当于把构造器作为命名空间来使用。

     /* -- 封装 -- */
var classA =function(){
//私有属性和方法
var name ='Xin';
var method1 =function(){
//...
}
//特权属性和方法
this.age ='20' ;
this.getName =function(){
return name;
}
}
//共有静态属性和方法
classA._name ='Darren code';
classA.alertName =function(){
console.log(_name);
}
//共有属性和方法
classA.prototype = {
init:function(){
//.....
},
init2:function(){
//.....
}
}

四:继承:

1.类式继承  (组合继承)

     //超级类(父类)
function Persion(name){
this.name = name;
}
Persion.prototype.getName = function(){
return this.name;
} //(子类)
function Author(name, books){
Persion.call(this, name);//调用超类的构造函数,把name作为参数传过去
this.books = books;
}
Author.prototype = new Persion();//子类的原型指向超类的实例,同时就会拥有超类的原型所指向的内存所拥有的方法和属性。
Author.prototype.constructor = Author;//因为子类的原型对象等于超类的实例,所以prototype.constructor这个方法也等于超类构造函数,所以要重新指定constructor.
Author.prototype.getBooks = function(){
return this.books;
}

首先创建构造函数,然后创建子类,通过call(this,arguments)来调用构造函数。然后设置原型链,js没有extend, so........ 就用prototype 来做继承。关于原型,不理解就自己看书吧,基础......要扎实........

子类的prototype是一个实例,就会拥有父类的prototype 属性,然后通过父类的prototype来找这块内存中存在的方法或者属性。

为了简化类的声明,可以把派生子类的整个过程包装在一个extend的函数中。

     function extend(subClass,superClass){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
}
但是,这样存在一个问题。就是同名函数会被复写,可以添加一个superclass属性来解决这个问题。
     function extend(subClass,superClass){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass; subClass.superclass = superClass.prototype;//添加superclass属性
if(superClass.prototype.constructor == Object.prototype.constructor){
superClass.prototype.constructor = superClass;
}
} function Author(name, books){
Author.superclass.constructor.call(this, name);
this.books = books;
}
extend(Author, Persion);
Author.prototype.getBooks = function(){
return this.books;
}
有了superclass属性,子类便可定义跟父类重名的原型方法,使用其原有函数的逻辑。
     Author.prototype.getName = function(){
var name = Author.superclass.constructor.getName.call(this);
return name + ",Author of" + this.getBooks().join(',');
}

//类式继承用到了原型链....原型链不懂的自己研究去吧.....

2.原型式继承

     /* -- 原型式继承 -- */
//clone()函数用来创建新的类Person对象
var clone =function(obj){
var _f =function(){};
//这句是原型式继承最核心的地方,函数的原型对象为对象字面量
_f.prototype = obj;
returnnew _f;
}
//先声明一个对象字面量
var Person = {
name:'Darren',
getName:function(){
returnthis.name;
}
}
//不需要定义一个Person的子类,只要执行一次克隆即可
var Programmer = clone(Person);
//可以直接获得Person提供的默认值,也可以添加或者修改属性和方法
alert(Programmer.getName())
Programmer.name ='Darren2'
alert(Programmer.getName()) //声明子类,执行一次克隆即可
var Someone = clone(Programmer);

总结:

类式继承(组合继承):使用原型链继承共享的属性和方法,而通过借用构造函数(   call( _ , _ )   )继承实例属性.

原型式继承:可以在不必预先定义构造函数的情况下实现继承,其本质是执行对给定对象的浅复制。而复制得到的副本还可以得到进一步改造。

类式继承,子类的原型指向一个父类的实例;原型式继承,子类的原型指向了父类的一个对象字面量(浅复制)。(子类都可能对父类的属性和方法进行修改。)

原型式继承会更省内存:被克隆出来的对象都共享每个属性和方法的唯一一份实例。而类式继承创建的每一个对象在内存中都有自己的一套属性(和私用方法)的副本。

最后:掺元类........

JavaScript设计模式——前奏(封装和信息隐藏)的更多相关文章

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

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

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

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

  3. JavaScript设计模式——前奏

    Function.prototype.method = function(name,fn){ this.prototype[name] = fn; } var Anim = function(){ / ...

  4. JavaScript设计模式-6.封装

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. JavaScript设计模式之一封装

    对于熟悉C#和Java的兄弟们,面向对象的三大思想(封装,继承,多态)肯定是了解的,今天我想讲讲如何在Javascript中利用封装这个特性,开讲! 我们会把现实中的一些事物抽象成一个Class并且把 ...

  6. 《JavaScript设计模式》笔记之第三章:封装和信息隐藏

    第三章 创建对象的基本模式 方法一:门户大开型 var Book = function(isbn, title, author) {   if(isbn == undefined ) throw ne ...

  7. 《javascript设计模式》读书笔记二(封装和隐藏信息)

    1.为什么要封装和信息隐藏 做过编程的朋友们知道"耦合"这个词.事实上封装的效果就是为了解耦,让类和类之间没有太多的联系,防止某一天改动某一类的时候,产生"多米骨诺牌效应 ...

  8. Javascript设计模式(1)

    本文是学习了<JavaScript设计模式>(谢廷晟 译)做的学习笔记 一.JavaScript的灵活性 1. 普通 functon function startAnimation() { ...

  9. Javascript设计模式笔记

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

随机推荐

  1. CentOs7 网卡出现问题Job for network.service failed

    centos7网卡是需要写入MAC地址的不然启动不了 在运行“/etc/init.d/network restart”命令时,出现错误“Job for network.service failed.  ...

  2. DREAMWEAVER

    女孩儿!!!Coding之路,你没有什么不一样的!!!! 1024,程序员的节日,开会的时候,你对负责人说今天是我们的节日哎~~结果,得到的是负责人冷冰冰的眼神:“你还真把自己当程序员了!?” 一阵愣 ...

  3. 闭包(block)

    block主要解决反向传值和传值问题 1.block申明的公式       返回值类型 (^名字)(参数列表); 2.block实现的公式       名字= ^(参数列表){}; 3.局部变量   ...

  4. Qt 获取cmd运行结果

    http://www.cnblogs.com/gisbeginner/archive/2012/12/08/2809063.html BOOL ExecDosCmd(){ #define EXECDO ...

  5. HTML标记语法之表格元素

    语法与语义: <table>和</table>定义表格的开始和结束 <thead>和</thead>定义表格头部的开始和结束 <tbody> ...

  6. [Android] 解析android framework下利用app_process来调用java写的命令及示例

    reference to :http://bbs.9ria.com/thread-253058-1-1.html 在android SDK的framework/base/cmds目录下了,有不少目录, ...

  7. August 14th, Week 34th Sunday, 2016

    To live is to function, that is all there is in living. 活着就要发挥作用,这就是生活的全部内容. I often joke that my dr ...

  8. poj1611(并查集)

    题目链接:http://poj.org/problem?id=1611 题意: SARS(非典型肺炎)传播得非常厉害,其中最有效的办法是隔离那些患病.和患病者接触的人.现在有几个学习小组,每小组有几个 ...

  9. iOS中的两种主要架构及其优缺点浅析

    凡是程序的开发者,应该对程序的架构都不陌生.一个程序的架构的好坏对这个程序有着非常重要的作用.今天我们来看一下iOS开发中用要的两种主流的程序架构.这个过程中我们主要以例子的形式展开. 我们来看第一种 ...

  10. Linux 压缩系列常用命令

    tar 命令: http://man.linuxde.net/tar zip 命令: http://man.linuxde.net/zip unzip 命令: http://man.linuxde.n ...