首先要了解一下面向?qū)ο蟮母拍睿?/p>
JS是一種基于對象的語言,和其它面向?qū)ο笳Z言不同
對象
一.如何創(chuàng)建一個對象:
第一種方法:創(chuàng)建對象的方式:
?var obj = new Object(); 利用new實例化出一個obj對象;
里面的屬性和方法可以自定義

第二種用字面量的方式:直接設(shè)置一個obj,在里面設(shè)置屬性和值;

工廠模式
軟件工程領(lǐng)域的一種設(shè)計模式,抽象了創(chuàng)建對象的過程,通過函數(shù)封裝創(chuàng)建對象的細節(jié):

這種方法比較簡單明了并且動態(tài),但是也有弊端:
1.看不出類型(如果比如寫的是new的別的對象,那么其實也可以執(zhí)行,也可以打印出來,很容易造成錯誤)
===》解決方法:構(gòu)造函數(shù);
2.函數(shù)重復、浪費資源 (利用傳參的方式,每次寫一次,函數(shù)就要執(zhí)行一次,會造成服務器壓力大)
===》解決方法:原型;
構(gòu)造函數(shù)怎么寫:
構(gòu)造函數(shù)一般以大寫字母開頭
構(gòu)造函數(shù)也是函數(shù),只不過可以用來創(chuàng)建對象
與工廠模式對比,沒有顯式創(chuàng)建對象,直接將屬性和方法賦給了this對象,沒有return

原型:prototype 是指原型 原型本身就是一個對象,因此我們只是在原型對象里創(chuàng)造了一個方法

★推薦使用原型+構(gòu)造函數(shù)結(jié)合的方法,既可以解決看不出類型的問題,又可以解決重復函數(shù)執(zhí)行,浪費資源;
★在原型上寫的新的方法,方法名不要和原來就有的方法重名,不然會產(chǎn)生覆蓋;(比如trim)
我們已知trim方法可以去除前后的空格,那么我們?yōu)槭裁催€要用正則,而不直接使用trim呢?
因為trim有兼容問題,(trim有trimRight 、trimLeft、trimStart、trimEndie11不兼容;?本身的trim兼容):
面向?qū)ο蟾呒墸?br>
如何繼承:
用原型繼承鏈 prototype:(這個不是直接繼承):

??但是會有一個問題,本來的原型被覆蓋了,那么我們怎么辦?
我們需要手動添加他的本來一個原型:構(gòu)造函數(shù).prototype.constructor =構(gòu)造函數(shù)本身;

原型鏈繼承-直接繼承prototype:
對上一種方法的改進
由于Person對象中,不變的屬性都可以直接寫入Person.prototype。所以,可以讓Man()跳過 Person(),直接繼承Person.prototype;
優(yōu)點:效率比較高(不用執(zhí)行和建立Person的實例了)
缺點:Man.prototype和Person.prototype現(xiàn)在指向了同一個對象,任何對Man.prototype的修改,都會反映到Person.prototype

利用空對象作為中介:其實這幾種方法就是在進行一步又一步的優(yōu)化:
空對象的好處:既可以繼承,但是又不會影響子類的原型;

然后再精簡化一下,把空對象函數(shù)封裝一下:

構(gòu)造函數(shù)綁定:掌握構(gòu)造函數(shù)綁定實現(xiàn)繼承,改變this的指向:
1.用call的方法:

2.用apply的方法:apply的方法和call方法是一樣的,只是call一個一個傳遞的,而apply需要用數(shù)組的方式來傳遞;

3.用bind方法來改變this執(zhí)行:
bind方法執(zhí)行完返回的是一個函數(shù),
想要執(zhí)行,就要加括號去執(zhí)行
?添加參數(shù)的第一種方法: obj1.fn.bind(obj2)("愛釣魚","愛看手機")?
添加參數(shù)的第二種方法: obj1.fn.bind(obj2,"愛釣魚","愛看手機")()?
那么bind和apply還有call有什么區(qū)別呢?:返回的是一個函數(shù);

通過call方法掌握構(gòu)造函數(shù)綁定實現(xiàn)繼承:

通過apply的方法掌握構(gòu)造函數(shù)綁定實現(xiàn)繼承:

通過bind方法掌握構(gòu)造函數(shù)綁定實現(xiàn)繼承:

組合繼承:
也叫偽經(jīng)典繼承:將原型鏈繼承和構(gòu)造函數(shù)繼承組合在一塊
利用call/apply/bind只能繼承父類實例屬性的繼承,不能繼承父類原型上的屬性和方法,所以要借助于原型鏈繼承;

拷貝繼承:
把父對象的所有屬性和方法,拷貝進子對象

ES6的繼承方式:class的繼承:
ES6繼承實際上是一種語法糖,底層就是原型鏈繼承==通過new父類的實例給到子類的原型上
父類 可以把構(gòu)造函數(shù)為類class,利用構(gòu)造器constructor來傳遞參數(shù),或設(shè)置自身的屬性和方法,不需要寫function,子類 ?子類繼承父類 通過關(guān)鍵詞 extends實現(xiàn),利用super關(guān)鍵字來調(diào)用父類的構(gòu)造函數(shù),super就代表父類;

ps:我們可以通過使用instanceof的方法,來判斷實例是哪一個類的實例,如果屬于,返回true,不屬于返回false
原型鏈繼承的方式:子類的實例是屬于父類的
拷貝以及構(gòu)造函數(shù)(call,apply,bind)的方式:子類的實例是不屬于父類的
