js 继承思想

在学习继承之前,我们要知道一个概念,那就是原型原型对象
原型对象:原型对象是构造函数(也就是非箭头函数)所特有的一块区域,用来共享实例间的数据。
原型就是[[prototype]]指向的区域,所有的引用类型都具有[[prototype]]属性。
还需要了解一个知识,构造函数的实例对象中的原型,默认指向该构造函数的原型对象,并且js在查找数据时,会顺着原型链向上查找,直到寻找到原型链的终点null返回undefined
好了,现在我们进入主题,了解js的继承机制。

1. 使用原型链继承

思想: 让派生构造函数的原型对象指向父构造函数的实例。

  • 优势:所有派生构造函数的实例都可以使用父构造函数原型对象中的方法
  • 不足:所有派生构造函数的实例共用同一个父构造函数实例的属性colors
        function SuperType (){
            this.colors = ['red', 'black'];
        }
        function SubType(){
            this.name = '哈哈'
        }
        SubType.prototype = new SuperType();
        let instance1 = new SubType();
        let instance2 = new SubType();
        instance1.colors.push('white')
        console.log(instance2.colors);// ['red', 'black', 'white']

由于原型链的继承方式的不足,我们引入了一种新的继承法方式。

2. 盗用构造函数

思想: 在派生构造函数中调用父构造函数

  • 优点:继承了父构造函数中的属性,并且实例间不在共享
  • 不足:派生构造函数的实例不可以使用父构造函数原型对象中方法
  function SuperType (){
            this.colors = ['red', 'black'];
        }
        SuperType.prototype.getColors = function(){
            console.log(this.colors);
        }
        function SubType(){
            SuperType.call(this);
        }
        let instance1 = new SubType();
        let instance2 = new SubType();
        instance1.colors.push('blue')
        console.log(instance2.colors)// ['red', 'black']
        console.log(instance1.colors) // ['red', 'black', 'blue']

这样我们将原型链盗用构造函数两种继承方式优势相结合,就产生了一种新的继承方式。

3. 组合继承

思想: 结合了原型链和盗用构造函数的思想。

  • 优点:实现了继承的基本模式,派生构造函数实例中有了父构造函数的属性,并且实例之间不会共享,也可以使用父构造函数原型对象中的方法。
  • 不足:可以看到,父构造函数执行了两次,第一次是将其实例对象赋值给oldPeople的时候,第二次是创建子实例的时候。
function People( gender ){
	this.gender = gender;
}
People.prototype.say = function () {
	console.log('我的性别', this.gender, this. age);
}
function oldPeople(name, gender, age){
	People.call(this, sex);
	this.name = name;
	this.age = age;
}
oldPeople.prototype = new People();
let oldWoman = new oldPeople('小红', '女', 80);
let oldMan = new oldPeople('小明', '男', 81);
oldWoman.say(); // 我的性别是女 80
oldMan.say();// 我的性别是女 81

4. 原型式继承

思想: 将子对象的原型指向父对象

  • 优点:不需要单独创建构造函数,就可以在对象间共享信息
  • 不足:同原型继承一样,子对象共享父对象的属性
    该种继承方式规范化其实就是Object.create的静态方法
    function object (o) {
        function F() {}
        F.prototype = o;
        return new F();
    }
    let person = {
        name: '小明',
        friends: ['小红','小绿']
    }
    let clone = object(person);

5. 寄生式继承

思想: 该思想同原型式继承一样,只是为对象新增了一个新的方法

        function object(o){
            function fn (){};
            fn.prototype = o;
            return new fn();
        }
        function createAnother( original ){
            let clone = object(original)
            clone.sayHi = function(){
                console.log('Hi');
            }
            return clone;
        }
        let person = {
            name: '小明',
            friends: ['小红', '小蓝']
        }
        let anotherPerson = createAnother(person);
        anotherPerson.sayHi();

6. 寄生式组合继承

思想: 使用寄生式继承来继承父类原型,然后盗用构造函数的思想继承父类属性。
寄生式继承可以算是引用类型继承的最佳模式了

        function SuperType (name){
            this.name = name;
        }
        SuperType.prototype.sayName = function(){
            console.log(this.name)
        }
        function SubType(age, name){
            SuperType.call(this, name);
            this.age = age
        }
        function inheritPrototype (SubType, SuperType){
            let prototype = SuperType.prototype;
            prototype.constructor = SubType;
            SubType.prototype = prototype;
        }
        inheritPrototype(SubType, SuperType);
        SubType.prototype.sayAge = function (){
            console.log(this.age);
        }
        let person1 = new SubType(12, '小明');
        let person2 = new SubType(18, '小红');
        person1.sayAge();
        person1.sayName();
        person2.sayAge();
        person2.sayName();

以上就是 js中 实现继承的全部方式,在ES6之后,出现了 class 和 extends,其背后思想其实就是使用构造函数的继承来实现的。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员-石头山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值