js 继承

function Person(name?) {       //Person 构造函数
    this.name = name ? name: 'wq';
    this.sayHi = function() {
        console.log('您好');
    }
}
Person.prototype.age = 30; //构造函数原型上加 age 属性
var person = new Person();//实例化对象
person.sex = '男';       // 实例对象上添加 sex 属性

1、原型链继承

function P1() {}  
P1.prototype = new Person(); //P1 的原型对象直接为 Person 的实例对象
var p1 = new P1();
//输出结果
p1.name;     //wq
p1.sayHi(); // 您好
p1.age;    //29  
p1.sex;   //undefined

  重点:子类的原型直接赋值了父类的原型,根据原型链查找对应属性值。

  特点:子类可继承父类属性:构造函数内属性、原型对象属性、实例对象属性无法继承。

  缺点:1、无法向构造函数传参  2、继承单一  3、共享父类属性,继承属性不能单独存在

2、共享原型模式继承

function P2() {}
P2.prototype = Person.prototype; // P2 共享了 Person 的原型对象
var p2 = new P2();

p1.name;   // undefined
p1.sex;   //  undefined
p1.age;  //   29
p1.say();//   报错

重点:子类共享使用了父类的原型,只能继承父类原型属性。

缺点:构造函数属性和实例属性无法继承;单一;无法传参;继承属性不独立。

3、借用构造函数继承

function P3(name) {
    Person.call(this,name); // call 改变 this 指向到 Person ,盗用其属性
}
var p3 = new P3('wq');

p3.name;   // wq
p3.sex;   //  undefined
p3.age;  //   undefined
p3.say();//   您好

重点:call 或 apply 将父类构造函数引进子类构造函数,继承父类构造函数属性;

           子类存在和父类构造函数相同属性,就近原则取值。

            call 和 apply 写在最前面

特点:只能继承父类构造函数属性,不能继承原型及其实例属性

           可以传值(一个或多个),解决了原型链及其共享原型单一、传参、数据共享问题。

缺点:无法实现构造函数复用,每次使用都要调用

           每个实例函数都有父类构造函数副本,臃肿

4、组合式继承(原型链 + 构造函数)

function P4(name) {
    Person.call(this,name); // call 改变 this 指向到 Person ,盗用其属性
}
P4.prototype = new Person(); // 包含构造函数属性及其原型属性
var p4 = new P4('wq');

p4.name;   // wq
p4.sex;   //  undefined
p4.age;  //   29
p4.say();//   您好

         重点:传参、复用

         特点:继承父类的构造函数方法,可传参可复用;新实例构造函数的属性都是私有属性。

         缺点:调用两次父类构造函数(耗内存)

var person = {
 name: 'wq',
 age: 29,
 sex: '男',
 sayHi:function() {
    console.log('您好');
 }
}

5、原型式继承

function createObj(person) {
    // 方法一:
    function P5(){};
    P5.prototype = person;   // 基于以存在对象实现,构造函数原型赋值为以存在对象
    return new P5();

    方法二:
    return Object.create(person);
}
var p5 = createObj(person);

p4.name;   // wq
p4.sex;   //  男
p4.age;  //   29
p4.say();//   您好

        重点:基于一个以存在对象实现,将以存在对象直接赋值构造函数原型。Object.create(null)

        特点:对象复制

        缺点:所有构造函数原型共享一个对象,导致相互影响,无法复用。

6、寄生式继承

function createObj(person) {
    // 方法一:
    function P5(){};
    P5.prototype = person;   // 基于以存在对象实现,构造函数原型赋值为以存在对象
    return new P5();

    方法二:
    return Object.create(person);
}

function create(person) {
    return createObj(person);
}
var p5 = create(person);

p4.name;   // wq
p4.sex;   //  男
p4.age;  //   29
p4.say();//   您好

        重点:寄生式继承给原型式继承再多套一层壳子(函数)

7、寄生组合式继承

// 寄生式继承
function createObj(person) {
    function P7(){};
    P7.prototype = person;   // 基于以存在对象实现,构造函数原型赋值为以存在对象
    return new P7();
}

function create(person) {
    return createObj(person);
}
var p7 = create(Person.prototype); // p7.__.proto__ === Person.prototype

//构造函数继承
function Constructorextend(){
    Person.call(this);
}
Constructorextend.prototype = p7; // Constructorextend 实例既包含 Person 原型属性又包含其构造函数属性
p7.constructor = Constructorextend; //改变其数据类型
var p8 = new Constructorextend();

p4.name;   // wq
p4.sex;   //  男
p4.age;  //   29
p4.say();//   您好

重点:寄生继承使其继承父类的原型属性;构造函数继承使其继承父类的构造函数属性;原型链继承使其构造函数的原型为寄生式继承的对象;因从父类继承需要改变其 constructor 为其子类本身。

8、ES6 继承

class Person {
    constructor (name?){
        this.name = 'wq' || name;
    }
    sayHi() {
        console.log('您好');
    }
}

// 使用 extends 继承其父类

class P8 extends Person {
    constructor() {
        super();
    }
}

var p8 = new P8();
p8.name; // 'wq'
p8.say();//'您好'

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值