它是一种编程思想 (object-oriented programming ), 咱们的编程或者学习实际上是按照类、实例
来完成的学习类的
继承、封装、多态
javascript
封装
java
把实现一个功能的代码封装到一个函数中(一个类中),之后再想实现这个功能,只须要执行这个函数方法便可,不须要再重复的编写代码。低耦合,高内聚
减小页面中的冗余代码,提升代码的重复使用率web
多态
编程
一个类(函数)的多种形态:重载、重写
【重载】
后台java,c#等编程语言中,对于重载的概念:方法名相同参数不一样,叫作方法的重载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,'word') //第三个
JS中没有相似于后台严格意义上的重载,JS中若是方法名相同,最后只能保留一个(和实参没有关系)
JS中的重载:同一个方法,经过传递实参的不一样(arguments)咱们完成不一样的功能,咱们把这个也理解为重载
function sum(num1,num2){ return num1+num2; } function sum(){ var ary=Array.prototype.slice.call(arguments) return eval(ary.join('+')); } sum(10,20) sum(10,20,30);// =>无论哪一次执行的都是第二个sum
无论是后台语言仍是js都有重写:子类重写父类的方法
什么是继承?
子类继承父类中的一些属性和方法
1.原型继承
webstorm
让子类的原型指向父类的实例
Children.prototype=new Parent();
function Parent(){ this.x=10; } Parent.prototype.getX=function(){ console.log(this.x) } function Child(){ this.y=20; } Child.prototype=new Parent(); //最好都在扩展子类原型方法以前执行 Child.prototype.constructor=Child; Child.prototype.getY=function(){ console.log(this.y); } var child=new Child(); console.log(child.y); child.getY(); child.getX() console.log(child.x);
[细节]
1.咱们首先让子类的原型指向父类的实例,而后再向子类原型上扩展方法,防止提早增长方法,等原型从新指向后,以前在子类原型上扩展的方法失效(子类原型已经指向新的空间地址了)
2.让子类原型从新指向父类实例,子类原型上原有的constructor就没有了,为了保证构造函数的完整性,咱们最好给子类的原型从新设置constructor属性值:Children.prototype.constructor=Children
[原理]
原型继承,并非把父类的属性和方法copy一份给子类,而是让子类的原型和父类原型之间搭建一个连接的桥梁,之后子类或者子类的实例能够经过原型链的查找机制,找到父类原型上的方法,从而调取这些方法使用便可。[特征]
子类不只能够继承父类原型上的公有属性方法,并且父类提供给实例的那些私有属性的方法,也被子类继承了(存放在子类原型上,做为子类公有的属性和方法)编程语言
2.call继承
函数
在子类的构造体中,把父类作普通方法执行,让父类方法中this指向子类的实例
function Parent(){ this.x=10; } Parent.prototype.getX=function(){ console.log(this.x); } function Children(){ //=>this:child 子类的实例 Parent.call(this); //让Parent执行,方法中的this依然是子类中的实例(在父类构造体中写this.xxx=xxx都至关于给子类的实例增长一些私有的属性和方法) this.y=20; } var child=new Children(); console.log(child.x);
【原理】
把父类构造体中私有的属性和方法,原封不动复制了一份给子类的实例(继承完成后,子类和父类是没有关系的);公有的没法继承。【细节】
咱们通常把call继承放在子类构造体的第一行,也就是建立子类实例的时候,进来的第一件事就是先继承,而后再给实例赋值本身私有的(好处:本身的能够把继承过来的结果替换掉--若是有重复的状况下)oop
3.寄生组合继承
学习
Object.create: 建立一个空对象,把obj做为新建立对象的原型 低版本不兼容
var obj={name:'hello word'} var newObj=Object.create(obj); newObj.__proto__===obj
寄生组合式继承完成了一个需求
子类公有的继承父类公有的(原型继承的变通)
子类私有的继承父类私有的(call继承完成)
function Parent(){ this.x=10; } Parent.prototype.getX=function(){ console.log(this.x) } function Children(){ Parent.call(this) this.y=20; } Children.prototype=Object.create(Parent.prototype); Children.prototype.constructor=Children; Children.getY=function(){ console.log(this.y); } var child=new Children(); console.log(child.x); child.getX()
本身实现一个相似于Objcet.create的方法
Object.myCreate=function myCreate(obj){ var Fn=new Function(); Fn.prototype=obj; return new Fn(); } var oo={name:'o'} Object.myCreate(oo)
4.ES6中的类和继承
class Fn{ constructor(a){ //=>constructor:Fn //=>这里面的this.xxx=xxx是给当前实例设置的私有属性 this.xxx=a } //=>这里设置的方法都放在Fn.prototype上(给实例提供的公有属性方法) //=>getX $ setX:都是给Fn.prototype设置方法 getx(){ } setX(){ } //=>static 这些属性和方法都是Fn当作普通对象设置的私有属性和方法,和实例没有任何的关系 static private(){ } } let f=new Fn(10,20);
class A{ constructor(){ this.x=10 } getX(){ console.log(this.x); } } class B extends A{ constructor(){ super(); //=>原理call继承, 第一句必须写上super() this.y=20; } getY(){ console.log(this.y); } } let b=new B();
5.for in循环遍历细节问题
Object.prototype.hasPubProperty=function hasPubProperty(){ } /* * for in循环 不只能够遍历当前对象(或者当前实例)全部的私有属性和方法,还能够把原型上本身建立的公共属性方法进行遍历 * * for 只会遍历私有的属性和方法(更多的是索引),本身在原型上扩展的方法不会被遍历出来 * */ var obj={name:'tom',age:8} for (const objKey in obj) { //webstorm 快捷键 itin if(obj.hasOwnProperty(objKey)){ console.log(objKey); } // console.log(objKey); // hasPubProperty } var ary=[12,23,34]; for (let i = 0; i < ary.length; i++) { console.log(ary[i]); } for (const aryKey in ary) { //快捷键 itar console.log(ary[aryKey]); }
webStorm本身配置快捷键 file-> setting->liveTemplates 右侧+本身DIY