面向对象OOP-12

2016-09-03-day12 am


面向对象的理解:

面向对象三大特点:
封装:将一个/一类事物的属性和功能集中定义在一个对象中 (为了代码重用!)
继承:父对象中的成员,子对象无需重复创建,即可直接使用。(为了即代码重用,又节约内存)
多态:同一个方法,在不同情况下,表现出不同的状态。(为了体现子对象与父对象之间的差异。)

继承: js中的继承都是通过原型对象实现的,也称之为原型继承/继承原型。

1.原型对象(prototype):

  • 什么是原型对象:集中存储一类对象共有成员的父对象。
  • 何时用原型对象: 只要多个子对象中,拥有相同的成员,就都要集中定义在父对象(原型对象)中一份,然后所有子对象共用!
  • 如何用原型对象:
    1.如何创建: 在创建构造函数时,会自动创建该类型的原型对象prototype
    2.何时继承: new的第二步,设置新对象的__proto__属性继承构造函数的原型对象
    3.如何向原型对象中添加共有成员:类型名.prototype.共有成员名=值

2.原型链: 由各级父对象逐级继承,实现的链式结构。

任何对象都由__proto__继承其父对象

Object.prototype是所有对象的顶级父对象。Object.prototype.__proto__是null
Function.prototype是所有函数对象的父对象。Function.prototype.__proto__是Object.prototype

原型链控制着成员的使用顺序:
优先使用当前对象本地的自有成员
如果自己没有,才延原型链向父级找
如果到Object.prototype没找到,返回undefined。

3.正确的访问对象的成员:

原则: 修改原型链上的共有成员:必须用父对象改。修改自有成员: 必须用当前子对象本身。禁止使用子对象修改共有成员

4.如何判断成员是自有还是共有:

自有: 直接定义在当前对象本地的成员
共有: 对象本地没有,从原型链上继承来的成员。

判断自有:
//判断"成员名"是否直接定义在obj本地
var bool=obj.hasOwnProperty("成员名")  
//如果是自有,就返回true,
//否则返回false
判断共有:

不是自有,且原型链上有

!obj.hasOwnProperty("成员名")&&(obj.成员!==undefined)
//或
"成员名" in obj

注:in: 判断"成员名"是否包含在obj的原型链上。(可检查整个原型链)

5.删除: delete obj.属性名

注:不能用子对象删除共有属性

pm


1.扩展内置对象的API:

  • 为什么: 解决浏览器兼容性问题
  • 何时: 如果想在旧的浏览器上,使用新浏览器的API,就需要再旧浏览器扩展内置对象的API
  • 如何: 都是将自定义的API添加到指定类型的原型对象上。

2.原型API:

2.1获得原型对象:2种:

通过构造函数获得: 构造函数.prototype
通过子对象获得: obj.__proto__ 兼容性
Object.getPrototypeOf(obj)获得obj对象的父对象(原型对象)

2.2判断指定对象是否是子对象的父对象:

father.isPrototypeOf(child),判断father对象,是否是child对象的父对象。
如果father是child的父对象,就返回true,否则返回false
强调: 检查整个原型链

2.3判断指定对象是否是指定构造函数的实例:

child instanceof 构造函数(mather),判断child是不是被构造函数实例化出的
强调: 也检查整个原型链

2.4鄙视题: 判断一个对象是不是数组类型, 有几种办法?

typeof: 只能识别原始类型和函数,无法进一步区分不同的引用类型
1.isPrototypeOf
2.instanceof
3.class属性: 记录了对象创建时的类型名,一旦对象创建,不可更改,只有Object.prototype中的toString方法才能输出class属性
问题: 内置对象的原型对象中都重写了新的toString方法,阻碍了子对象直接调用原始的toString方法
解决: 用call强行调用!要调用方法的完整签名.call(调用方法的对象)
4.Array.isArray(obj),专门用于检测obj是不是数组类型,原理同第三种方法

总结:
call: 用一个对象强行调用一个本来无法调用到的函数。
何时: 希望打破原型链的限制,直接调用一个本不可调用的函数
如何: 要调的函数.call(对象)

添加一个新方法,如何选择加在构造函数上,或者加在原型对象中?
如果希望指定类型的所有子对象都可访问时,就放在原型对象中——必须通过实例化的对象调用(也成为实例方法)
如果无法确定将来调用函数时的对象的类型,就不能放在原型对象中。要放在构造函数上。——static静态方法

3.多态:

重写(override): 如果子对象觉得父对象继承来的成员不好用,就可在本地定义和父对象成员同名的自有成员。优先使用自有成员,而屏蔽了父对象的共有成员。

1. 自定义继承(3种方法):

1). 修改一个对象继承另一个父对象:
child.__proto__=father;
 => Object.setPrototypeOf(
       child,father
    )  
//设置child继承father
2). 批量修改所有子对象的父对象:

时机: 在开始创建子对象之前,就修改原型对象。
构造函数.prototype=father

3). 两种类型间的继承:

问题: 两种类型间,有部分相同的属性结构,和共同的方法。
解决: 抽象出一个公共的父类型
将子类型中相同的部分属性和方法,定义到父类型中。

如何实现两种类型间的继承:

1)). 设置子类型的原型对象继承父类型的原型对象。

 Object.setPrototypeOf(
   子类型的原型对象,
   父类型的原型对象
 );

2)). 借用父类型的构造函数: 父类型构造函数.call(this,参数,...)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 10,717评论 0 21
  •   面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意...
    霜天晓阅读 6,466评论 0 6
  • 面向对象的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。ECMAScr...
    DHFE阅读 4,594评论 0 4
  • 我害怕—薛之谦 很多时候我都想拥抱你 哪怕时光之里山南水北 哪怕你我之间人来人往 我依旧要想你 依旧想要抱着你 未...
    南素简阅读 3,276评论 0 2
  • 原本以为,爱情和婚姻是两回事,可是,自从我喜欢上你,我便认为,爱情,和婚姻并无区别。 所有的等待,相聚,分离,争吵...
    迷人的hero阅读 3,038评论 4 0

友情链接更多精彩内容