注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Computer Science

I Pressed My Words Here. Will You Read ?

 
 
 

日志

 
 

(3.1)《JavaScript高级程序设计(第2版)》读书笔记(3.1)  

2010-12-16 20:39:37|  分类: 读书笔记 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
书名:JavaScript高级程序设计:第2版
豆瓣评分:9.3分(493人评价)
博主评价:
未评价很差较差还行推荐力荐
来自豆瓣读书资源
第6章 面向对象程序设计  —— 复用,在属性与方法间的纠结;继承,在构造函数与原型间的游走。
ECMAScript支持面向对象(OO)编程,但不是用类或者接口。对象可以在代码执行过程中创建和增强,因此具有动态而非严格定义的实体。在没有类的情况下,可以采用下列模式创建对象。
  • 工厂模式
  • 构造函数模式
  • 原型模式
  • 动态原型模式
  • 寄生构造函数模式
  • 稳妥构造函数模式
  • 各种继承模式
    • 组合继承
    • 原型式继承
    • 寄生式继承
    • 寄生组合式继承

下面记录各个模式之间的差异
模式名称 简介 解决的问题 主要缺陷
工厂模式
 使用简单的函数创建对象,为对象添加属性和方法,然后返回对象。这个模式后来被构造函数模式取代。解决了创建多个相似对象的问题。没有解决对象识别的问题(即怎样知道一个对象的类型) 。
构造函数模式
 可以自定义引用类型,可以像创建内置对象一样使用new操作符。不过,它的每个成员都无法得到复用,包括函数。由于函数可以不局限于任何对象(即与对象具有松散耦合的特点),因此没有理由不在多个对象间共享函数。
这个模式的不足被原型模式弥补。
 解决对象类型识别问题。 构造函数中每个方法都要在每个实例上重新创建一遍。
 解决方法 引入的问题
 將构造函数的属性保留在构造函数中定义,而构造函数的方法只在内部引用,放到构造函数外定义。
  1. 在构造函数外部定义的方法占用了全局作用域,而并没有充分利用这个作用域 。
  2. 定义的这个引用类型没有封装。
  
原型模式
  使用构造函数的prototype属性来指定那些应该共享的属性和方法。
组合使用的构造函数模式和原型模式时,使用构造函数定义实例属性,而使用原型定义共享的属性和方法。
 通过在调用构造函数而创建的对象的原型对象中,写入可在构造函数的对象实例间共享属性和方法,避免在构造函数中直接定义。 省略了构造参数传递初始化参数这一环节,结果所有实例在默认情况下都將取得相同的属性值。
特别是对于原型中的引用型的属性/方法对象,一旦构造函数的对象实例对其作出修改,将会影响所有对象实例中的对应属性/方法。
 解决方法 引出的问题
组合使用构造函数模式和原型模式,详见简介栏。 构造函数和原型分离,未体现面向对象的形式。
解决
方法
动态原型模式
  
  
动态原型模式
  通过在构造函数中初始化原型(仅在必要情况下),保持同时使用构造函数和原型的优点。
在构造函数中初始化原型前,通过在构造函数中检查某个应该存在的方法是否有效,来决定是否需要初始化原型。
 使用动态原型模式时,不能使用对象字面量重写原型。如果在已经创建了实例的情况下重写原型,那么就会切断现有实例于新原型之间的联系。已经比较好了,暂无修改必要。
寄生构造函数模式
  在上面几种模式都不适用的情况下,可以使用寄生(parasitic)构造函数模式。
这种模式的基本思想是创建一个函数,该函数的作用仅仅是分装创建对象对的代码,然后再返回新创建的对象(从表面上看,很像是典型的构造函数,起到了封装的作用,和工厂模式有得一比)。
返回的对象与构造函数或者与构造函数的原型属性之间没有关系;即,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。因此无法通过instanceof操作符来确定对象类型!
 与工厂模式比较
  • 缺陷相同。
  • 此模式中用到的包装函数被称作构造函数,而在工厂模式中,完全相同的包装函数被视作包含必要信息的对象函数。
  • 此模式用到new操作符实例化构造函数,而工厂模式將包装函数视作对象,无需实例化。
  
稳妥构造函数模式
  稳妥对象(durable objects):没有公共属性,其它地方不应用this的对象。
适合在一些(禁止使用this和new)的安全环境中,或者在防止数据被其他应用程序(如Mashup程序)改动时使用。
此模式和工厂模式及寄生构造函数模式有得一比。
和工厂模式的缺陷相同。
 与工厂模式比较
 此模式在包装函数中新创建对象的实例方法不引用this。而工厂模式和寄生构造模式的包装函数中新创建对象时都用了this关键字。
此模式其它地方和工厂模式完全相同(不会像寄生函数模式中用new关键字实例化对象)。
  
各种继承模式
 ECMAScript中描述了原型链的概念,并將原型链作为实现继承的主要方法。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。简单回顾一下构造函数,原型和实例的关系:每个构造函数都又一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么,假如我们让原型对象等于另一个类型的实例,结果会怎样呢?显然,此时的原型对象將包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向其对应构造函数的指针。假如,另一个原型又是另一个类型的原型的实例,那么,上述关系依然成立,如此层层递进,就够成了实例与原型的链条。这就是所谓的原型链的基本概念。
原型链的缺陷:当原型B成为原型A的实例时,不但继承了原型A中属性和方法,同时也将原型A对应的构造函数A的属性(一般不会有方法的定义)继承到了原型B中,作为了原型的属性。于是,这些属性(方法也是,只是方法在设计中本就假设为共享)将成为原型B的实例间共享的属性。即,原型B的实例不会像原型A的实例那样拥有默认的独自的属性。自然,原型B的实例无法在不影响所有同级及以下的对象实例的情况下,给原型A对应的构造函数(SuperClass's Constructor)传递函数。
  简介解决的问题
主要缺陷 
 借用构造函数
Constructor Stealing
有时候也叫伪造对象或经典继承。基本思想是在子类行构造函数的内部通过使用apply()或call()方法来调用超类型构造函数。
避免了原型链中构造函数中定义的属性在子类中共享的问题的出现。
 和原型链恰恰相反,方法(属性自然也是)都將在构造函数中定义,函数的复用就因此不存在了。
同时,在超类型中定义的方法在子类中也將不可见,唯有构造函数可用了。
 组合继承
combination inheritance
也叫伪经典继承。其基本思路是使用原型链实现对原型属性和方法的继承;通过借用构造函数来实现对实例属性的继承。这样,即通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。
对冲了原型链和借用构造函数因各自的极端而引发的缺陷。
instanceof和isPrototypeOf()能够识别基于组合继承创建的对象。
 语言叙述结构上比较复杂,前后两次调用超类型构造函数,在子类型原型中创建了不必要的、多余的属性。
(call() apply()见本书Page99,犀牛Edition5 Page145)
 原型式继承 可以在不必预先定义构造函数的情况下实现继承,其本质是执行对给定对象的浅复制。而赋值得到的副本还可以得到进一步改造。 不创建构造函数,实现对象间的继承。避免代码的大量重复。 引用类型值在所有相关对象间共享。
 寄生式继承 寄生式继承和原型式继承紧密相关,思路上与工厂模式和寄生构造函数类模式似(更像工厂些)。
创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。
 在主要考虑对象,而不是自定义类型和构造函数的情况下,寄生式继承有效增强了对象的概念。使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率;这一点与构造函数模式类似。
 寄生组合式继承 综合了寄生式继承和组合继承,在组合继承的过程中,采用寄生式继承的函数,將超类型的原型赋给子类型的原型,并增强对象。 解决了组合继承过程调用两次构造函数带来的低效率。以及寄生式继承中函数无法复用带来的低效率。 作为目前引用类型最理想的继承范式。缺陷不太明显。
  
    

欢迎读者在留言中校订
  评论这张
 
阅读(165)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017