面向对象编程(OOP)
它是一种编程思想(Object Oriented Programming),我们的编程或者学习其实是按照
类、实例
来完成的学习类的
继承、封装、多态
封装
把实现一个功能的代码封装到一个函数中(一个类中),以后再想实现这个功能,只需要执行函数方法即可,不需要再重复的编写代码
低耦合,高内聚
减少页面中的冗余代码,提高代码的重复使用率
多态
一个类(函数)的多种形态:
重载、重写
[ 重载 ]
后台JAVA、C#等编程语言中,对于重载的概念:方法名相同参数不同,叫做方法的重载
public void sum(int num1,int num2){//=>CODE} public void sum(int num1){//=>CODE} public void sum(int num1,string str){//=>CODE} sum(12,23)sum(12)sum(12,'珠峰')
JS中没有类似于后台严格意义上的重载:JS中如果方法名相同了,最后只能保留一个(和实参没关系的)
JS中的重载:同一个方法,通过传递实参的不同(arguments)我们完成不同的功能,我们把这个也可以理解为重载
function sum(num1,num2){return num1+num2;}function sum(){var ary=[].slice.call(argumnets);return eval(ary.join('+'));}sum(10,20);sum(10,20,30);//=>不管哪一次执行的都是第二个SUM
不管是后台语言还是JS都有重写:子类重写父类的方法
类的继承
什么是继承?
子类继承父类中的一些属性和方法
原型继承
让子类的原型指向父类的实例
Children.prototype = new Parent();[细节]
1、我们首先让子类的原型指向父类的实例,然后再向子类原型上扩展方法,防止提前增加方法,等原型重新指向后,之前在子类原型上扩展的方法都没用了(子类原型已经指向新的空间地址了)
2、让子类原型重新指向父类实例,子类原型上原有的constructor就没有了,为了保证构造函数的完整性,我们最好给子类的原型重新手动设置constructor属性值:Children.prototype.constructor = Children;
[ 原理 ]
原型继承,并不是把父类的属性和方法COPY一份给子类,而是让子类的原型和父类原型之间搭建一个链接的桥梁,以后子类(或者子类的实例),可以通过原型链的查找机制,找到父类原型上的方法,从而调取这些方法使用即可[ 特征 ]
子类不仅可以继承父类原型上的公有属性和方法,而且父类提供给实例的那些私有的属性方法,也被子类继承了(存放在子类原型上,作为子类公有的属性和方法)
function Parent() {this.x = 100;}Parent.prototype.getX = function () {console.log(this.x);}; function Children() {this.y = 200;}Children.prototype = new Parent();//=>最好在扩展子类原型方法之前完成Children.prototype.constructor = Children;Children.prototype.getY = function () {console.log(this.y);}; var child = new Children();
call继承
在子类的构造体中,把父类做普通方法执行,让父类方法中的THIS指向子类的实例
function Parent() {this.x = 100;}Parent.prototype.getX = function () {console.log(this.x);};function Children() {//=>this:child 子类的实例Parent.call(this);//=>让Parent执行,方法中的THIS依然是子类的实例(在父类构造体中写的 THIS.XXX=XXX 都相当于在给子类的实例增加一些私有的属性和方法)this.y = 200;}var child = new Children();
[ 原理 ]
把父类构造体中私有的属性和方法,原封不动复制了一份给子类的实例(继承完成后,子类和父类是没关系的)[ 细节 ]
我们一般把call继承放在子类构造体中的第一行,也就是创建子类实例的时候,进来的第一件事情就是先继承,然后再给实例赋值自己私有的(好处:自己的可以把继承过来的结果替换掉)
寄生组合继承
Object.create([obj]):创建一个空对象(实例),把[obj]作为新创建对象的原型
var obj={name:'珠峰培训'};var newObj=Object.create(obj);newObj.__proto__===obj
寄生组合式继承完成了一个需求:
子类公有的继承父类公有的(原型继承的变通)
子类私有的继承父类私有的(call继承完成)
function Parent() {this.x = 100;}Parent.prototype.getX = function () {console.log(this.x);};function Children() {Parent.call(this);this.y = 200;}Children.prototype = Object.create(Parent.prototype);Children.prototype.constructor = Children;Children.prototype.getY = function () {console.log(this.y);};
思考题:
自己实现一个类似于Object.create的方法
Object.myCreate = function myCreate(obj) {var Fn = new Function();Fn.prototype = obj;return new Fn();};
ES6中的类及继承
创建类
class Fn {constructor(){//=>constructor:Fn//=>这里面的 this.xxx=xxx 是给当前实例设置的私有属性}//=>这里设置的方法都放在Fn.prototype上(给实例提供的公有属性方法)xxx(){}... //=>这写属性和方法都是把Fn当做普通对象设置的私有属性和方法,和实例没有任何的关系static xxx(){}...}var f = new Fn();
继承
class A {constructor() {this.x = 100;} getX() {console.log(this.x);}} class B extends A {constructor() {super();//=>CALL继承 进来第一句话必须写上super()this.y = 200;} getY() {console.log(this.y);}} var b = new B();