它是一種編程思想 (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