本文僅僅是記錄自己學(xué)習(xí)的心得體會(huì),如果有誤,歡迎指出,非原創(chuàng),具體請(qǐng)參考:《JavaScript設(shè)計(jì)模式》 張容銘 著
1.子類的原型對(duì)象繼承——類式繼承
//聲明父類
function ParentClass() {
this.ParentValue = true;
}
ParentClass.prototype.getParentValue = function () {
return this.ParentValue;
}
//聲明子類
function ChildClass() {
this.ChildValue = false;
}
ChildClass.prototype = new ParentClass();//繼承父類
ChildClass.prototype.getChildValue = function () {
return this.ChildValue;
}
這里實(shí)現(xiàn)繼承是將父類的實(shí)例賦予給了子類的原型
var newChild = new ChildClass();
console.log(newChild)
console.log(newChild.__proto__)
輸出結(jié)果:

這里的newChild是子類的實(shí)例,newChild的原型對(duì)象現(xiàn)在是父類的實(shí)例,這個(gè)時(shí)候newChild繼承了父類的屬性以及原型上的方法
使用:
var result = newChild .getChildValue();
var result1 = newChild .getParentValue();
console.log(result);//false
console.log(result1);//true
子類繼承的缺點(diǎn):
1.如果父類的屬性中含有引用類型,那么在子類中改變后,父類的屬性的值也會(huì)改變。
2.因?yàn)檫@種繼承是將父類的實(shí)例化對(duì)象賦給子類的原型,所以這里沒(méi)有辦法向父類傳遞參數(shù)
//聲明父類
function ParentClass() {
//引用類型屬性
this.booksName = ['JavaScript','CSS3','HTML5'];
}
ParentClass.prototype.getParentValue = function () {
return this.booksName;
}
//聲明子類
function ChildClass() {
this.ChildValue = false;
}
ChildClass.prototype = new ParentClass();
ChildClass.prototype.getChildValue = function () {
return this.ChildValue;
}
var newChild1 = new ChildClass();
var newChild2 = new ChildClass();
console.log(newChild2.booksName)//["JavaScript","CSS3","HTML5"]
newChild1.booksName.push('JQuery'); //別人修改這個(gè)值后
console.log(newChild2.booksName)//["JavaScript","CSS3","HTML5","JQuery"]
2.構(gòu)造式繼承
//聲明父類
function ParentClass(bookId) {
//引用類型屬性
this.booksName = ['JS','CSS3','HTML5']
this.id = bookId
}
//父類添加原型方法
ParentClass.prototype.getBooks = function () {
console.log(this.booksName)
}
//子類
function ChildClass(bookId) {
//繼承父類
ParentClass.call(this,(bookId))
}
//創(chuàng)建兩個(gè)子類實(shí)例對(duì)象
var newChild1 = new ChildClass(101);
var newChild2 = new ChildClass(102);
newChild1.booksName.push('JQ');
console.log(newChild1.booksName);//["JS","CSS3","HTML5","JQ"]
console.log(newChild1.id);//101
console.log(newChild2.booksName);//["JS","CSS3","HTML5"]
console.log(newChild2.id);//102
newChild1.getBooks();//Uncaught TypeError: newChild1.getBooks is not a function
call這個(gè)方法可以更改函數(shù)的作用環(huán)境,在子類中,對(duì)ParentClass調(diào)用這個(gè)方法,就是將子類的變量在父類中執(zhí)行了一遍。父類中是給this綁定屬性的,new對(duì)象的時(shí)候這個(gè)this指向new的對(duì)象(這里是newChild1 和newChild2),這樣就把父類的屬性都復(fù)制了到了這兩個(gè)實(shí)例化的對(duì)象上,所以當(dāng)我改變newChild1.booksName的時(shí)候沒(méi)有改變到newChild2.booksName的值
這種辦法既可以傳參,也可以防止父類中的引用類型屬性被修改,是不是剛好和類式繼承互補(bǔ)呢,SO?
3.組合式繼承
//聲明父類
function ParentClass(name) {
this.name = name
this.booksName = ['JS','HTML5','CSS3']
}
//父類原型公共方法
ParentClass.prototype.getBookName = function () {
console.log(this.name)
}
//聲明子類
function ChildClass(name,time) {
this.time = time
ParentClass.call(this,(name))
}
//類式繼承
ChildClass.prototype = new ParentClass()
//子類原型方法
ChildClass.prototype.getBookTime = function () {
console.log(this.time)
}
var book1 = new ChildClass('JQ',2011);
var book2 = new ChildClass('Vue',2015);
book1.getBookTime(); //2011
book1.getBookName(); //JQ
book1.booksName.push('React');
book2.getBookTime(); //2015
book2.getBookName(); //Vue
console.log(book1.booksName); //["JS", "HTML5", "CSS3", "React"]
console.log(book2.booksName); //["JS", "HTML5", "CSS3"]
4.原型式繼承
function innerObject(fn) {
function Fun() {
//new 一個(gè)過(guò)渡函數(shù)
}
Fun.prototype = fn; //過(guò)渡函數(shù)的原型指向傳入的對(duì)象
return new Fun(); //返回原型繼承了fn的實(shí)例
}
這種方法有缺點(diǎn):
1.和類似繼承很像,如果傳入的對(duì)象屬性中有引用類型,那么將產(chǎn)生和類似繼承一樣的問(wèn)題,公用了一個(gè)屬性,也會(huì)容易被其他的修改而發(fā)生改變
2.但是在此基礎(chǔ)上推進(jìn)可以得到寄生式繼承
5.寄生式繼承
function innerObject(fn) {
function Fun() {
}
Fun.prototype = fn;
return new Fun();
}
var book = {
bookName : 'js book',
alikeBooks : ['css book','html book']
};
function CreatBook() {
var newBook = innerObject(book);
newBook.getName = function () {
console.log(bookName)
}
return newBook;
}
var book1 = new CreatBook();
var book2 = new CreatBook();
book1.alikeBooks.push('JQ');
console.log(book1)
console.log(book2)
console.log(book1.alikeBooks)//['css book','html book','JQ']
console.log(book2.alikeBooks)//['css book','html book','JQ']
book1 && book2輸出結(jié)果:

書(shū)上說(shuō)“其實(shí)寄生式繼承就是對(duì)原型繼承的第二次封裝,并且在這第二次封裝的過(guò)程中對(duì)繼承的對(duì)象進(jìn)行了擴(kuò)展,這樣新創(chuàng)建的對(duì)象不僅有父類的屬性和方法,還添加新的屬性和方法”
6.寄生組合式繼承
function innerObject(fn) {
function Fun() {}
Fun.prototype = fn;
return new Fun();
}
function innerPrototypeObject(childClass, parentClass) {
//傳入父類的原型 得到繼承了父類原型的對(duì)象newChildClassPrototype
var newChildClassPrototype = new innerObject(parentClass.prototype);
//將繼承了父類原型的對(duì)象newChildClassPrototype 的構(gòu)造函數(shù)指向子類
newChildClassPrototype.constructor = childClass;
//重寫(xiě)子類的原型,newChildClassPrototype成為子類的原型
childClass.prototype = newChildClassPrototype;
}
測(cè)試:
function innerObject(fn) {
function Fun() {}
Fun.prototype = fn;
return new Fun();
}
function innerPrototypeObject(childClass, parentClass) {
//傳入父類的原型 得到繼承了父類原型的對(duì)象newChildClassPrototype
var newChildClassPrototype = new innerObject(parentClass.prototype);
//將繼承了父類原型的對(duì)象newChildClassPrototype 的構(gòu)造函數(shù)指向子類
newChildClassPrototype.constructor = childClass;
//重寫(xiě)子類的原型,newChildClassPrototype成為子類的原型
childClass.prototype = newChildClassPrototype;
}
function parentClass(bookname) {
this.name = bookname
this.color = ['red','blue','green']
}
parentClass.prototype.getName = function () {
console.log(this.name)
}
function childChass(bname,time) {
parentClass.call(this,(bname))//繼承父類屬性
this.time = time
}
innerPrototypeObject(childChass,parentClass);//繼承父類原型
childChass.prototype.getTime = function () {
console.log(this.time)
}
var newbook1 = new childChass('js',2015);
var newbook2 = new childChass('jq',2017);
console.log(newbook1)
console.log(newbook2)
newbook1.color.push('yellow');
console.log(newbook1.color); //['red','blue','green','yellow']
console.log(newbook2.color); //['red','blue','green']
newbook1.getTime(); //2015
newbook2.getName(); //jq
這里修改了實(shí)例newbook1的color這個(gè)屬性,但是并沒(méi)有影響到newbook2實(shí)例的屬性的值,newbook1&&newbook2輸出結(jié)果:
newbook1&&newbook2輸出結(jié)果.png

現(xiàn)在處于昏迷狀態(tài),讓我捋捋再改。