知识点:js继承的几种方式以及优缺点

总结:这几种方法都有很明显的优缺点,但都是为了怎么更好的做到同时继承原型+原型链上的方法和属性。比如以下例子:可以继承Parent的方法和属性,但怎样一并继承Parent.prototype的属性和方法?

原型链继承

缺点:原型属性会被共享(如果一个实例改变了该属性,那么其他实例的属性会随之改变)

function Parent(){
    this.arr = [1,2,3];
}
function Child(){}

Child.prototype = new Parent();  // 继承关键行

var child1 = new Child();
var child2 = new Child();

// 缺点
child1.arr.push(4)
console.log(child1.arr); // [1,2,3,4]
console.log(child2.arr); // [1,2,3,4]

构造函数继承

使用call或bind方法实现继承

优点:原型属性不会被共享

缺点:不会继承父类的prototype属性

function Parent(){
    this.sayHello = function(){
        console.log('Hello');
    };
}
Parent.prototype.a = "我是父类的prototype属性"
function Child(){
    Parent.call(this) //继承关键行
}


var child1 = new Child();
var child2 = new Child();
var parentObj = new Parent

// 优点
console.log(child1.sayHello === child2.sayHello); // false
// 缺点
console.log(parentObj.a); // "我是父类的prototype属性"
console.log(child1.a); //  undefined

组合继承

就是(原型链继承+构造函数继承)

优点:1.原型属性不会被共享 2.可以继承父类的prototype属性

缺点:调用了2次父类的方法

function Parent(){
    this.sayHello = function(){
        console.log('Hello');
    };
}
Parent.prototype.a = "我是父类的prototype属性"

function Child(){
    Parent.call(this) //继承关键行1
}
// 缺点:Child.prototype本身可以继承Parent.sayHello 但这里赋值new Parent() 也就是调用了2次Parent()
Child.prototype = new Parent();  // 继承关键行2 
var child1 = new Child();

// 优点
console.log(child1.a); //  "我是父类的prototype属性"

寄生组合继承

Object.create() 创建一个空对象,并且指定这个空对象的prototype 是谁

优点:解决了上面三种方法的缺点

缺点:子类的prototype上的属性和方法会丢失

function Parent(){
    this.sayHello = function(){
        console.log('Hello');
    };
}
Parent.prototype.a = "我是父类的prototype属性"

function Child(){
    Parent.call(this) // 继承关键行1
}
Child.prototype.ChildFun = ()=>{
    console.log("我是子类的方法")
}
// 优点 (创建一个没有实例的父类实例作为子类的原型)
Child.prototype = Object.create(Parent.prototype)    // 继承关键行2
// 修复构造函数的指向
Child.prototype.constructor = Child  // 继承关键行3
var child1 = new Child();

// 缺点
child1.ChildFun();  //  child1.ChildFun不是一个函数

 Class关键字继承:class继承 

拓展

如果对原型和原型链不熟

// 创建原型
function Parent(name){
    this.name= name;
}

// 原型上的方法
Parent.prototype.todo = ()=>{
console.log('做牛马')
} ; 

// 创建新的原型对象 会共享原型上的属性和方法
var child1 = new Parent('小鹿');

console.log(child1.todo) // 做牛马 (child1 首先会在原型Parent里面找有没有todo 的方法,如果没有,就会去Parent.prototype上面找,直到找到原型链的顶端Object.prototype)

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript中实现继承方式有以下几种: 1. 原型链继承 优点:简单方便,易于理解和实现。 缺点:父类的引用属性会被多个实例共享,可能会出现意外修改;子类无法向父类构造函数传递参数。 示例代码: ```javascript function Animal() { this.species = 'animal'; } function Cat() {} Cat.prototype = new Animal(); ``` 2. 借用构造函数继承 优点:可以在子类构造函数中向父类构造函数传递参数;解决了父类引用属性被多个实例共享的问题。 缺点:无法实现函数的复用。 示例代码: ```javascript function Animal(name) { this.name = name; } function Cat(name) { Animal.call(this, name); } ``` 3. 组合继承 优点:综合了原型链继承和借用构造函数继承的优点,既可以实现函数的复用,又可以向父类构造函数传递参数。 缺点:父类构造函数会被调用两次,造成了一些不必要的消耗。 示例代码: ```javascript function Animal(name) { this.name = name; } Animal.prototype.sayHello = function() { console.log('Hello, my name is ' + this.name); }; function Cat(name) { Animal.call(this, name); } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; ``` 4. 原型式继承 优点:简单方便,可以在不必创建构造函数的情况下实现继承。 缺点:引用属性会被共享,可能会造成意外修改。 示例代码: ```javascript function createObject(obj) { function F() {} F.prototype = obj; return new F(); } var animal = { species: 'animal' }; var cat = createObject(animal); ``` 5. 寄生式继承 优点:可以在不必创建构造函数的情况下实现继承,可以为对象添加专门的方法。 缺点:引用属性会被共享,可能会造成意外修改。 示例代码: ```javascript function createObject(obj) { var clone = Object.create(obj); clone.sayHello = function() { console.log('Hello, my name is ' + this.name); }; return clone; } var animal = { species: 'animal' }; var cat = createObject(animal); ``` 总体来说,不同的继承方式各有优缺点,应根据具体的需求来选择合适的方式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值