js各種繼承方式匯總
阿新 • • 發佈:2018-01-19
使用 bit 拷貝 prot urn str 返回 共享 ceo
3、來自原型對象的引用屬性是所有實例共享的
js中的各種繼承實現匯總
首先定義一個父類:
function Animal(name) {
this.name = name || '動物'
this.sleep = function () {
console.log(this.name + '正在睡覺!')
}
}
Animal.prototype.eat = function (food) {
console.log(this.name + '正在吃:' + food)
}
原型鏈繼承
特點:
1、子類的原型指向父類的實例
缺點:
1、無法多繼承
2、無法向父類的構造傳參
function Cat() { }
Cat.prototype = new Animal()
Cat.prototype.name = '貓'
// Test code
const cat = new Cat()
console.log(cat.name) // 貓
cat.eat('魚') // 貓正在吃:魚
cat.sleep() // 貓正在睡覺!
console.log(cat instanceof Cat) // true
console.log(cat instanceof Animal) // true
構造繼承(使用call、apply方式)
特點:
1、子類的構造中進行父類構造的調用
優點:
1、實現了多繼承,想繼承哪個直接在子類構造裏面call或者apply哪個就行
2、避免所有子類實例共享父類引用屬性問題
3、創建子類實例時,可以向父類傳遞參數
缺點:
1、沒用到原型,只是單純繼承了父類的實例屬性及方法
2、沒繼承原型上的屬性及方法
3、每個子類都有父類方法屬性的副本,影響性能,沒有實現父類函數復用
function Dog(name) {
Animal.call(this)
this.name = name || '狗'
}
// Test code
const dog = new Dog()
console.log(dog.name) // 狗
dog.sleep() // 狗正在睡覺!
// dog.eat('粑粑') 不能繼承原型上的eat
console.log(dog instanceof Dog) // true
console.log(dog instanceof Animal) // false,等於是復制父類的實例屬性給子類,沒用到原型
實例繼承
特點:
1、子類的構造中返回父類的實例
優點:
1、可以繼承原型上的屬性或方法
缺點:
1、實例為父類實例,而非子類實例
2、不能實現多繼承
function Pig(name) {
const instance = new Animal()
instance.name = name || '豬'
return instance
}
// Test code
const pig = new Pig()
console.log(pig.name) // 豬
pig.sleep() // 豬正在睡覺!
pig.eat('菠菜葉子') // 豬正在吃:菠菜葉子
console.log(pig instanceof Pig) // false
console.log(pig instanceof Animal) // true
復制繼承或拷貝繼承(暴力繼承)
特點:
1、子類的構造中強制拷貝父類原型上的屬性或方法
優點:
1、可以多重繼承
缺點:
1、效率較低,內存占用高
2、不能繼承父類不可枚舉的屬性(不能用for in遍歷的)
function Rabbit(name) {
const animal = new Animal() // 多重繼承直接new多個遍歷
for (let i in animal) {
Rabbit.prototype[i] = animal[i]
}
Rabbit.prototype.name = name || '兔子'
}
// Test code
const rabbit = new Rabbit('傻兔子')
console.log(rabbit.name) // 傻兔子
rabbit.sleep() // 傻兔子正在睡覺!
rabbit.eat('胡蘿蔔') // 傻兔子正在吃:胡蘿蔔
console.log(rabbit instanceof Rabbit) // true
console.log(rabbit instanceof Animal) // false
對象冒充繼承(類似於構造繼承)
同構造繼承
function Mouse(name) {
this.method = Animal
this.method(name)
delete this.method
}
// Test code
const mouse = new Mouse('老鼠')
console.log(mouse.name) // 老鼠
mouse.sleep() // 老鼠正在睡覺!
// mouse.eat('大米') // 繼承不到原型上的屬性
console.log(mouse instanceof Mouse) // true
console.log(mouse instanceof Animal) // false
組合繼承(構造繼承+原型鏈繼承)
特點:
1、組合構造繼承和原型鏈繼承
優點:
1、可以繼承實例屬性/方法,也可以繼承原型屬性/方法
2、既是子類的實例,也是父類的實例
3、不存在引用屬性共享問題
4、可傳參
5、函數可復用
缺點:
1、調用了兩次父類構造函數
function Duck(name) {
Animal.call(this, name)
}
Duck.prototype = new Animal()
Duck.prototype.say = function () { // 新增的say方法
console.log(this.name + '正在說話!')
}
// Test code
const duck = new Duck('鴨子')
console.log(duck.name) // 鴨子
duck.sleep() // 鴨子正在睡覺!
duck.eat('蟲子') // 鴨子正在吃:蟲子
console.log(duck instanceof Duck) // true
console.log(duck instanceof Animal) // true
寄生組合繼承
特點:
1、使用中間函數對象避免父類構造被兩次調用的問題
優點:
1、完美
缺點:
1、寫起來費勁
function Snake(name) {
Animal.call(this, name)
}
const Super = function () { }
Super.prototype = Animal.prototype
Snake.prototype = new Super()
// Test code
const snake = new Snake('蛇')
console.log(snake.name) // 蛇
snake.sleep() // 蛇正在睡覺!
snake.eat('小鳥') // 蛇正在吃:小鳥
console.log(snake instanceof Snake) // true
console.log(snake instanceof Animal) // true
ES6的class繼承
class Point {
constructor(x, y) {? //constructor 構造方法
this.x = x
this.y = y
}
toString() {
return this.x + ', ' + this.y
}
static hello() {
console.log('hello world!')
}
}
class ColorPoint extends Point {
constructor(x, y, color){
super(x, y) // 必須先調用super,否則子類的this不可用
this.color = color
}
toString() {
return this.color + ',' + super.toString()
}
}
// Test code
const cp = new ColorPoint(25, 8, 'green')
console.log(cp instanceof ColorPoint) // true
console.log(cp instanceof Point) // true
ColorPoint.hello() // hello world!
js各種繼承方式匯總