1.原型鏈
// 缺點(diǎn):1)引用類(lèi)型的屬性被實(shí)例所共享
// 2)在創(chuàng)建Child的實(shí)例時(shí),不能向Parent傳參
var log = console.log.bind(console)
function Parent () {
this.names = ['kevin', 'daisy'];
}
function Child () {}
Child.prototype = new Parent();
var child = new Child();
child.names.push('yayu');
console.log(child.names); // ["kevin", "daisy", "yayu"]
var child1 = new Child();
console.log(child1.names); // ["kevin", "daisy", "yayu"]
2.借助構(gòu)造函數(shù)设江,也叫偽造對(duì)象或經(jīng)典繼承锦茁。
// 優(yōu)點(diǎn):
// 1)避免了引用類(lèi)型的屬性被所有實(shí)例共享
// 2)可以在 Child 中向 Parent 傳參
// 缺點(diǎn):方法都在構(gòu)造函數(shù)中定義,每次創(chuàng)建實(shí)例都會(huì)創(chuàng)建一遍方法叉存。
var log = console.log.bind(console)
function Parent(name) {
this.name = name
this.getName = function() {
log(this.name)
}
}
function Child(name) {
Parent.call(this, name)
}
var child1 = new Child('kevin');
console.log(child1.name); // kevin
var child2 = new Child('daisy');
console.log(child2.name); // daisy
log(child1.getName == child2.getName) //false
3.組合繼承码俩。也叫偽經(jīng)典繼承。
// 優(yōu)點(diǎn):融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn)歼捏,是 JavaScript 中最常用的繼承模式稿存。
var log = console.log.bind(console)
function Parent (name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function () {
console.log(111, this.name)
}
function Child (name, age) {
// 借用構(gòu)造函數(shù)
Parent.call(this, name);
this.age = age;
}
// 原型繼承
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child('kevin', '18');
child1.colors.push('black');
console.log(child1.name); // kevin
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"]
var child2 = new Child('daisy', '20');
console.log(child2.name); // daisy
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]
log(child1.getName == child2.getName) //true
4.原型式繼承
// ES5 Object.create 的模擬實(shí)現(xiàn),將傳入的對(duì)象作為創(chuàng)建的對(duì)象的原型瞳秽。
// 缺點(diǎn):包含引用類(lèi)型的屬性值始終都會(huì)共享相應(yīng)的值瓣履,這點(diǎn)跟原型鏈繼承一樣
var log = console.log.bind(console)
function createObj(o) {
function F(){}
F.prototype = o;
return new F();
}
var person = {
name: 'kevin',
friends: ['daisy', 'kelly']
}
var person1 = createObj(person);
var person2 = createObj(person);
// 注意:修改person1.name的值,person2.name的值并未發(fā)生改變练俐,并不是因?yàn)閜erson1和person2有獨(dú)立的 name 值袖迎,而是因?yàn)閜erson1.name = 'person1',給person1添加了 name 值痰洒,并非修改了原型上的 name 值瓢棒。
person1.name = 'person1';
console.log(person2.name); // kevin
person1.friends.push('taylor');
console.log(person2.friends); // ["daisy", "kelly", "taylor"]
5.寄生式繼承
// 創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù),該函數(shù)在內(nèi)部以某種形式來(lái)做增強(qiáng)對(duì)象丘喻,最后返回對(duì)象脯宿。
// 缺點(diǎn):跟借用構(gòu)造函數(shù)模式一樣,每次創(chuàng)建對(duì)象都會(huì)創(chuàng)建一遍方法泉粉。
function createObj(o) {
var clone = Object.create(o)
clone.sayName = function() {
log('hi')
}
return clone
}
6.寄生組合式繼承(是引用類(lèi)型最理想的繼承范式)
// 避免了組合繼承的:2次調(diào)用父級(jí)的構(gòu)造函數(shù)
function object(o) {
function F() {}
F.prototype = o
return new F()
}
function prototype(child, parent) {
var prototype = object(parent.prototype) //創(chuàng)建對(duì)象
child.constructor = child //增強(qiáng)對(duì)象
child.prototype = prototype
}
function Parent(name) {
this.name = name
this.colors = ['red', 'blue', 'green']
}
Parent.prototype.getName = function() {
log(this.name)
}
function Child(name, age) {
Parent.call(this, name)
this.age = age
}
// 避免了組合繼承的:2次調(diào)用父級(jí)的構(gòu)造函數(shù)
// Child.prototype = new Parent()
prototype(Child, Parent)
var child1 = new Child('haha', 19)
child1.getName()
child1.colors.push('yellow')
log(child1.colors)
log('-----------', child1)
var child2 = new Child('meimei', 20)
child2.getName()
log(child2.colors)
log('-----------', child2)
// 這個(gè)方法也是公共的
log(child1.getName == child2.getName)
詳見(jiàn):查看打印