原型链继承,将父类的实例作为子类的原型,他的特点是实例是子类的实例也是父类的实例,父类新增的原型方法/属性,子类都能够访问,并且原型链继承简单易于实现,缺点是来自原型对象的所有属性被所有实例共享,无法实现多继承,无法向父类构造函数传参。
构造继承,使用父类的构造函数来增强子类实例,即复制父类的实例属性给子类,构造继承可以向父类传递参数,可以实现多继承,通过call多个父类对象。但是构造继承只能继承父类的实例属性和方法,不能继承原型属性和方法,无法实现函数服用,每个子类都有父类实例函数的副本,影响性能
实例继承,为父类实例添加新特性,作为子类实例返回,实例继承的特点是不限制调用方法,不管是new 子类()还是子类()返回的对象具有相同的效果,缺点是实例是父类的实例,不是子类的实例,不支持多继承
拷贝继承:特点:支持多继承,缺点:效率较低,内存占用高(因为要拷贝父类的属性)无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)
组合继承:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
1. 使用原型链的方法实现
// 原型链继承
function Person() {
this.name = 'zs'
this.age = 20
}
Person.prototype.getName = function () {
return this.age
}
function Child() { }
Child.prototype = new Person()
let hd = new Child()
console.dir(hd.getName());
2. 借用构造函数实现
function Person(){
this.name = 'zs'
this.age = 20
}
function Child(){
Person.call(this)
}
let hd = new Child()
3. 使用组合式方法实现继承
缺点是实现继承需要调用两次父类构造函数
function Parent(name){
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function(){
console.log(this.name);
}
function Child(name,age){
Parent.call(this,name);// 第二次调用 Parent()
this.age = age;
}
Child.prototype = new Parent(); // 第一次调用 Parent(
4. 原型式继承
// 原型式继承 使用Object.create方法重新创建一个对象实现
// 包含引用类型的属性值始终都会共享相应的值, 这点跟原型链继承一样
function objectCreate(obj) {
function fn() { }
fn.prototype = obj
return new fn()
}
let person = {
name: 'zs', age: 20
}
let hd = objectCreate(person) // 手写实现Object.create
let ob = Object.create(person) // es6出现的
console.log(hd.name);
console.log(ob.name);
5. 使用函数方法继承
跟构造函数一样 使用前 每次创建对象时都需要在创建一次对象
function createObj(obj) {
let newobj = Object.create(obj)
newobj.view = function () {
this.name = 'zs'
this.age = 20
return this.name
}
return newobj
}
let o = {
name: 'ls', age: 21
}
let hd = createObj(o)
console.dir(hd.view());
6. 寄生组合式继承
// 实现一个继承的方法 extend
function _extend(child, parent) {
child.prototype = Object.create(parent.prototype)
Object.defineProperty(child.prototype, 'constructor', {
value: child,
enumerable: false
})
}
function User() {
this.name = 'user'
this.view = function () {
return this.name
}
}
function Admin() {
this.name = 'admin'
this.view = function () {
// this.name = 'admin'
return this.name
}
}
Admin.prototype.getAdmin = function () {
this.age = 21
this.name = 'admin'
return this.age
}
_extend(User, Admin)
let dh = new User()
console.dir(dh.getAdmin()); // 21
console.dir(dh.name); // admin
console.dir(dh); // User
7. es6语法extends
class Child extends Parent{}