孩兒們棺滞,來繼承為父的遺產(chǎn)吧,咳咳咳咳矢渊。開個玩笑继准。繼承理解為取存在對象已有屬性和方法的一種方式.,那么我們有幾種方式可以實現(xiàn)呢矮男。接下來請開始個人showtime移必。
- 1.原型鏈繼承
原理:我們都知道在實例中查找該屬性,如果找到了毡鉴,返回該值崔泵,否則,通過__proto__找到原型對象猪瞬,在原型對象中進行搜索憎瘸,如果找到,返回該值陈瘦,否則幌甘,繼續(xù)向上進行搜索,直到找到該屬性,或者在原型鏈中沒有找到锅风,返回undefined酥诽。
function Parent() {
this.name = '爸爸';
this.family = ['媽媽','哥哥'] //驗證引用類型的屬性會被所有實例共享
}
Parent.prototype.getName = function() {
console.log(this.name)
console.log(this.family )
}
function Child() {}
Child.prototype = new Parent();
var child = new Child();
child.getName() // '爸爸' ["媽媽", "哥哥"]
child.family.push('姐姐')
var child2 = new Child();
child2.getName() // '爸爸' ["媽媽", "哥哥", "姐姐"]
給你們畫個靈魂圖你們就知道了為啥是這樣的結(jié)果 --。--
缺點: 引用類型的屬性會被所有實例共享,在創(chuàng)建Child實例時不能想Parent傳參
- 2 借用構(gòu)造函數(shù)(經(jīng)典 經(jīng)典 經(jīng)典 重要的事情說三遍)
function Parent (name) {
this.name = name;
this.family = ['媽媽','哥哥']
this.getName = function() {
console.log(this.name)
console.log(this.family)
}
}
function Child(name) {
Parent.call(this,name) //重點是這個哦
}
var child = new Child(爸爸)
child.getName() // '爸爸' ["媽媽", "哥哥"]
child.family.push('姐姐')
var child2 = new Child('我');
child2.getName() // '我' ["媽媽", "哥哥"]
我們明顯的可以看到了與上一個相比避免了引用類型的屬性被所有實例共享皱埠,而且我們還可以從Child中向Parent傳參哦
- 3 組合繼承(雙劍合并來了)
function Parent(name) {
this.name = name;
this.family = ['媽媽','哥哥']
}
Parent.prototype.getName = function () {
console.log(this.name)
console.log(this.family)
}
function Child(name) {
Parent.call(this,name)
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child('我');
child1.family.push('爸爸');
child1.getName(); // 我 ["媽媽", "哥哥", "爸爸"]
var child2 = new Child('你')
child2.getName(); // 你 ["媽媽", "哥哥"]
console.log(Child.prototype.constructor)
優(yōu)點怎么說肮帐,集兩家之長吧,是JavaScript中最常用的繼承模式(ps:你覺得到這就可以了吧边器,呵呵训枢,你還太年輕了往下看)。
- 4原型式繼承 (不是原型鏈繼承哦)
function createObj(o) {
function F(){};
F.prototype= o;
return new F();
}
var parent = {
name : '我',
family : ['媽媽','哥哥']
}
var child1 = createObj(parent);
var child2 = createObj(parent);
console.log(child1.name); // 我
child1.name = "你";
console.log(child2.name); // 我
// 注意這里并不是因為child1和child2有獨立的name值饰抒,而是因為child1.name直接給
// child1添加了屬性肮砾,并沒有去影響原型上的name值
console.log(child1.family ); //["媽媽", "哥哥"]
child1.family.push('爸爸');
console.log(child2.family ); // ["媽媽", "哥哥", "爸爸"]
簡單理解就是把傳入的對象變成了創(chuàng)建對象的原型,然后返回這個對象袋坑,就類似與我把對象的prototype寫成了一個參數(shù)仗处。
- 5 寄生組合式繼承 -------------------------快瘋了--------------------------
創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式增強對象(給對象添加屬性和方法), 然后返回該對象
function createObj(o) {
var clone = Object.create(o);
clone.say = function () {
console.log('我是新增的方法咯')
}
return clone;
}
有木有感覺和原型式繼承差不多枣宫,不過上一個是修改創(chuàng)建對象的原型婆誓,這個是直接修改對象的屬性和方法。
缺點: 每次創(chuàng)建對象都會創(chuàng)建一遍方法
6 寄生組合式繼承
我們重顧一下
孩兒們也颤,來繼承為父的遺產(chǎn)吧洋幻,咳咳咳咳。開個玩笑翅娶。繼承理解為取存在對象已有屬性和方法的一種方式.文留,那么我們有幾種方式可以實現(xiàn)呢。接下來請開始個人showtime竭沫。1.原型鏈繼承
原理:我們都知道在實例中查找該屬性燥翅,如果找到了,返回該值蜕提,否則森书,通過__proto__找到原型對象,在原型對象中進行搜索谎势,如果找到凛膏,返回該值,否則脏榆,繼續(xù)向上進行搜索猖毫,直到找到該屬性,或者在原型鏈中沒有找到须喂,返回undefined吁断。
function Parent() {
this.name = '爸爸';
this.family = ['媽媽','哥哥'] //驗證引用類型的屬性會被所有實例共享
}
Parent.prototype.getName = function() {
console.log(this.name)
console.log(this.family )
}
function Child() {}
Child.prototype = new Parent();
var child = new Child();
child.getName() // '爸爸' ["媽媽", "哥哥"]
child.family.push('姐姐')
var child2 = new Child();
child2.getName() // '爸爸' ["媽媽", "哥哥", "姐姐"]
給你們畫個靈魂圖你們就知道了為啥是這樣的結(jié)果 --典唇。--
缺點: 引用類型的屬性會被所有實例共享,在創(chuàng)建Child實例時不能想Parent傳參
- 2 借用構(gòu)造函數(shù)(經(jīng)典 經(jīng)典 經(jīng)典 重要的事情說三遍)
function Parent (name) {
this.name = name;
this.family = ['媽媽','哥哥']
this.getName = function() {
console.log(this.name)
console.log(this.family)
}
}
function Child(name) {
Parent.call(this,name) //重點是這個哦
}
var child = new Child(爸爸)
child.getName() // '爸爸' ["媽媽", "哥哥"]
child.family.push('姐姐')
var child2 = new Child('我');
child2.getName() // '我' ["媽媽", "哥哥"]
我們明顯的可以看到了與上一個相比避免了引用類型的屬性被所有實例共享,而且我們還可以從Child中向Parent傳參哦
- 3 組合繼承(雙劍合并來了)
function Parent(name) {
this.name = name;
this.family = ['媽媽','哥哥']
}
Parent.prototype.getName = function () {
console.log(this.name)
console.log(this.family)
}
function Child(name) {
Parent.call(this,name)
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child('我');
child1.family.push('爸爸');
child1.getName(); // 我 ["媽媽", "哥哥", "爸爸"]
var child2 = new Child('你')
child2.getName(); // 你 ["媽媽", "哥哥"]
console.log(Child.prototype.constructor)
優(yōu)點怎么說胯府,集兩家之長吧,是JavaScript中最常用的繼承模式(ps:你覺得到這就可以了吧恨胚,呵呵骂因,你還太年輕了往下看)。
- 4原型式繼承 (不是原型鏈繼承哦)
function createObj(o) {
function F(){};
F.prototype= o;
return new F();
}
var parent = {
name : '我',
family : ['媽媽','哥哥']
}
var child1 = createObj(parent);
var child2 = createObj(parent);
console.log(child1.name); // 我
child1.name = "你";
console.log(child2.name); // 我
// 注意這里并不是因為child1和child2有獨立的name值赃泡,而是因為child1.name直接給
// child1添加了屬性寒波,并沒有去影響原型上的name值
console.log(child1.family ); //["媽媽", "哥哥"]
child1.family.push('爸爸');
console.log(child2.family ); // ["媽媽", "哥哥", "爸爸"]
簡單理解就是把傳入的對象變成了創(chuàng)建對象的原型,然后返回這個對象升熊,就類似與我把對象的prototype寫成了一個參數(shù)俄烁。
- 5 寄生組合式繼承 -------------------------快瘋了--------------------------
創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式增強對象(給對象添加屬性和方法), 然后返回該對象
function createObj(o) {
var clone = Object.create(o);
clone.say = function () {
console.log('我是新增的方法咯')
}
return clone;
}
有木有感覺和原型式繼承差不多级野,不過上一個是修改創(chuàng)建對象的原型页屠,這個是直接修改對象的屬性和方法。
缺點: 每次創(chuàng)建對象都會創(chuàng)建一遍方法
- 6 寄生組合式繼承
我們重顧一下
function Parent(name) {
this.name = name;
this.family = ['媽媽','哥哥']
}
Parent.prototype.getName = function () {
console.log(this.name)
console.log(this.family)
}
function Child(name) {
Parent.call(this,name)
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child('我');
child1.family.push('爸爸');
child1.getName(); // 我 ["媽媽", "哥哥", "爸爸"]
var child2 = new Child('你')
child2.getName(); // 你 ["媽媽", "哥哥"]
console.log(Child.prototype.constructor)
發(fā)現(xiàn)我們會調(diào)用兩次父構(gòu)造函數(shù)蓖柔。
一次是設(shè)置子類型實例原型的時候
Child.prototype = new Parent();
一次是創(chuàng)建子類型實例的時候
var child1 = new Child('我');
而其在這里我們也會調(diào)用一次Parent構(gòu)造含糊
Parent.call(this,name)
那么我們怎么避免重復(fù)調(diào)用呢辰企?加入我們是間接的讓Child.prototype 訪問到Parent.prototype呢
function Parent(name) {
this.name = name;
this.family = ['媽媽','哥哥']
}
Parent.prototype.getName = function () {
console.log(this.name)
console.log(this.family)
}
function Child(name) {
Parent.call(this,name)
}
// 關(guān)鍵在這
var F = function() {}
F.prototype = Parent.prototype;
child.protype = new F();
var child1 = nwe Child('我')
console.log(child)
這樣是不是減少了一次調(diào)用父構(gòu)造函數(shù)new Parent()
來我們封裝一下這個繼承方法
function object(o) {
function F() {};
F.prototype = o;
return new F();
}
function prototype(child,parent) {
var prototype = object(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}
prototype(Child,Parent);
而其還避免了在Parent.prototype上面創(chuàng)建不必要的多余的屬性,于此同時况鸣,原型鏈還能保持不變牢贸。開發(fā)人員普遍認為寄生式組合式繼承是引用類型最理想的繼承范式。
有沒有搞的頭昏镐捧,最后一個潜索,多看幾遍 哈哈哈哈