面向对象
目标:实现代码重用性、灵活性和扩展性
特点:功能模块化,代码复用性号,易于维护
怎样实现OOP
## 对客观事实进行抽象
## 一般实物存在一些特点和特定行为
## 特点抽象成属性
## 行为抽象成方法
封装
然后把属性和方法进行集成到一个实体中,这就是OOP的封装
## OPP有三个特点:封装 继承 多态
## 封装就是将客观实物的特点和行为抽象为属性和方法,集成到一个实体,这个实体就是我们说的对象Object
## 一个对象有特定的属性与功能,调用者无需知道他的内部构造,只需调用它的方法即可实现特定功能,这就是面向对象的特点,无需关注其内部实现,换句话说,我不需要关注这个对象是怎么去实现这个功能的,我只知道调用它就可以完成这个功能,这就是面向对象
## 面向过程恰恰就关注的是实现过程,将一个过程拆分为多个过程,对每一个过程使用特定功能的函数实现,面向过程不关注这件事是谁做的,只关注怎么实现的,也就是连续的函数的执行
面向对象与面向过程相比,在维护性上,和复用性上是一个很大的提升
继承
继承就是更高层次的复用,比如有一个类 叫 Cat 还用一个 类 叫 Dog ,但是这个时候我想对Animal也抽象一下,怎么办???
Cat Dog Animal
都是动物这种概念 总不能给cat dog 就换个名字,内部结构一样吧,就算他们可以换个名字,那Animal怎么办 ?总不能cat dog Animal 这三个除了名字不一样,其余的属性方法都一样吧,很明显这是不合理的
按照客观逻辑 Cat Dog 应该是 Animal 这个实体的分支,Cat Dog 的共性应该在 Animal上体现出来
所以,就出现了继承的概念
继承是更高层次的抽象
怎样实现继承
## JS内部使用的是prototype属性和__proto__属性完成继承,一个构造函数的实例的__proto__指向他的构造函数的prototype属性,在此声明一下,函数也是一个对象
所有的非函数对象和函数对象最终都指向了Obejct.prototype,而非Object,instanceof表示两侧的对象是同一条原型链上 并不是说非得谁是谁的实例
每一个对象都有一个__proto__属性,指向他的构造函数的prototype
如果他的构造函数的prototype指向未被手动改变,就是指向Object.prototype
Object.prototype.__proto__指向的是NULL
实现继承的方法
- 原型继承
原型继承有很多种
【A】在实例的构造函数上添加属性和方法,实例就可以获取到这些属性
【B】把一个实例的原型对象直接指向另一个实例,但是需要修改constructor指向
【C】直接让当前实例的构造函数的原型指向另一个构造函数的原型,也要修改constructor指向
【D】借助一个空的匿名函数来实现继承
function fun(){}
function A(){.....}
function B(){.....}
让B继承A
fun.prototype = A.prototype
var f1= new fun()
B.prototype=f1
B.prototype.constructor = B
B的实例都可以共享A的prototype数据
而且,修改B的prototype还不会影响A的prototype
function A(){}
function B(){}
function C(){}
A.prototype.a=5;
B.prototype = A.prototype;
var b = new B()
C.prototype=b;
console.log(A.prototype)
console.log(B.prototype)
console.log(C.prototype)
C.prototype.b=7;
C.prototype.constructor = C;
console.log(A.prototype)
console.log(B.prototype)
console.log(C.prototype)
- call apply
- Object.create
- class继承