js继承介绍

目录

原型链的继承

借用构造函数继承

组合继承

原型式继承

寄生式继承

 寄生组合式继承

完整例子(class类编译后的代码)

 

 

原型链的继承

 function SuperType(){
     this.property = true;
 }      
 SuperType.prototype.getSuperValue = function(){
     return this.property;
 };       
  function SubType(){
       this.subproperty = false;
 }       
 //inherit from SuperType
 SubType.prototype = new SuperType();
       
 SubType.prototype.getSubValue = function (){
     return this.subproperty;
 };
        

实现方法:

某一(理解为子类)原型对象等于另一(理解为父类)类型的实例

本质:

就是重写了子类的原型对象(所以需要注意的就是,通过使用原型链继承,就不能再使用对象字面量去创建原型方法,因为这样会再次重写原型链),子类原型对象包含一个指向父类原型对象的指针。

这样继承之后:

父类中的实例属性会在子类的原型对象中,父类中的原型中的东西依然在父类原型对象中。子类原型对象里面不会有constructor属性,除非自己补上

原型链带来的问题:

1、父类中的实例属性会变成子类原型对象中的属性

2、在创建子类型的实例时,不能向父类型的构造函数中传递参数

借用构造函数继承

function SuperType(){
     this.colors = ["red", "blue", "green"];
}

 function SubType(){  
     //inherit from SuperType
      SuperType.call(this);
}
  var instance1 = new SubType();
        instance1.colors.push("black");
        alert(instance1.colors);    //"red,blue,green,black"
        
        var instance2 = new SubType();
        alert(instance2.colors);    //"red,blue,green"

实现方法:

子类型构造函数内部直接调用父类函数(当然,要通过apply或call改变this指向)

本质:父类中实例属性的继承,就是子类实例属性中有父类实例属性的副本

继承之后:子类实例属性中有父类实例属性的副本

优点与问题:优点:子类构造函数中调用父类构造函数的时候可以向其传递参数

            缺点:方法写在构造函数中,函数的复用无从谈起,而且父类原型对象中定义的方法,子类并不可见,所以就有了原型链与借用构造函数相结合的组合继承

组合继承

就是利用原型链实现对原型对象中属性和方法的继承,利用借用构造函数实现对实例属性的继承。

懂了前面两个,这个来个例子看看就会明白

    function SuperType(name){
            this.name = name;
            this.colors = ["red", "blue", "green"];
        }
     
    SuperType.prototype.sayName = function(){
            alert(this.name);
        };

    function SubType(name, age){  
            SuperType.call(this, name);//构造函数继承
            this.age = age;
        }

    SubType.prototype = new SuperType();//原型链继承
        
    SubType.prototype.sayAge = function(){
        alert(this.age);
    };
        
    var instance1 = new SubType("Nicholas", 29);
    instance1.colors.push("black");
    alert(instance1.colors);  //"red,blue,green,black"
    instance1.sayName();      //"Nicholas";
    instance1.sayAge();       //29
       
    var instance2 = new SubType("Greg", 27);
    alert(instance2.colors);  //"red,blue,green"
    instance2.sayName();      //"Greg";
    instance2.sayAge();       //27
       

但是呢,组合继承也有它的缺点。大家有没有发现,在组合继承中,有两次调用了父类的构造函数,第一次在原型链继承的地方,就是子类的原型对象中会存储父类构造函数里属性和方法;第二次调用是在子类的构造函数内,这样 父类构造函数里属性和方法又会变成子类实例的属性和方法,所以就有屏蔽子类原型中的。

如何解决这个问题,就是待会会说到的寄生组合式继承。

 

原型式继承

 function object(o){//原型式继承 
     function F(){}  
     F.prototype = o;  //以传进来的对象为基础,返回的实例中,改实例的原型对象指向o
     return new F();
 }
        

原型式继承首先在object()函数内部创建一个临时性的构造函数 ,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。

所有的实例都是共享这一个原型对象(就是在一个实例中更改了原型中的值,其他实例中的值也会有更改)

看例题:

function object(o){//原型式继承 
  function F(){}
  F.prototype = o;
  return new F();
}

var person = {
  name: "Nicholas",
  friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = object(person);
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.friends.push("Barbie");

alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"

//稍微优化
(function object(){//原型式继承 
  function F(){}
  return function(o){
      F.prototype = o;
      return new F();
  }
})()

寄生式继承

这种继承方式是把原型式+工厂模式结合起来,目的是为了封装创建的过程。


    function create(o){        
        var f= object(o);
        f.run = function () {            
            return this.arr;//同样,会共享引用
        };       
     return f;
    }

 寄生组合式继承

根据组合继承改进,原有的借用构造函数继承不变,改变原型链继承的方式,不通过调用父类构造函数,而是通过以下方法:

第一步:创建父类原型的一个副本(利用原型式继承)

第二步:增强上面创建的对象

第三步:将上面创建的对象赋值给子类对象的原型

实现代码如下:

function inheritPrototype(subType,superType) {
    var prototype = object(superType.prototype);//第一步
    prototype.constructor = subType;//第二步
    subType.prototype = prototype;//第三步
}

function create(o){        
    var f= object(o);
    f.run = function () {            
        return this.arr;//同样,会共享引用
    };       
    return f;
}

function object(o){//原型式继承 
    function F(){}
    F.prototype = o;
   return new F();
}

完整例子(class类编译后的代码)

        var __extends = (this && this.__extends) || (function () {
            var extendStatics = function (d, b) {
                // 兼容
                extendStatics = Object.setPrototypeOf ||
                    ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                    function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
                return extendStatics(d, b);
            }
            return function (d, b) {
                // 继承静态属性
                extendStatics(d, b);
                // 原型式继承
                function __() { this.constructor = d; }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
            };
        })();
        var Animal = /** @class */ (function () {
            function Animal(theName) {
                this.name = theName;
            }
            Animal.hi = function(){console.log('hi')}
            Animal.prototype.move = function (distanceInMeters) {
                if (distanceInMeters === void 0) { distanceInMeters = 0; }
                console.log(this.name + " moved " + distanceInMeters + "m.");
            };
            return Animal;
        }());
        var Snake = /** @class */ (function (_super) {
            __extends(Snake, _super);// 静态方法和原型式继承
            function Snake(name, age) {
                // 为什么一定要写super(),编译的时候不能直接加进去?我觉得是为了继承父类中的属性,还可以传值进行初始化,没写super编译后就是var _this,下面也拿不到this对象
                var _this = _super.call(this, name) || this;//借用父类构造函数继承父类的实例属性和方法到子类的实例上  
                _this.age = age;
                return _this;
            }
            Snake.prototype.move = function (distanceInMeters) {
                if (distanceInMeters === void 0) { distanceInMeters = 5; }
                console.log("Slithering...");
                _super.prototype.move.call(this, distanceInMeters);
            };
            return Snake;
        }(Animal));
       
        var sam = new Snake("Sammy the Python");
        sam.move();
        Snake.hi()

 

 

内容概要:本文介绍了奕斯伟科技集团基于RISC-V架构开发的EAM2011芯片及其应用研究。EAM2011是一款高性能实时控制芯片,支持160MHz主频和AI算法,符合汽车电子AEC-Q100 Grade 2和ASIL-B安全标准。文章详细描述了芯片的关键特性、配套软件开发套件(SDK)和集成开发环境(IDE),以及基于该芯片的ESWINEBP3901开发板的硬件资源和接口配置。文中提供了详细的代码示例,涵盖时钟配置、GPIO控制、ADC采样、CAN通信、PWM输出及RTOS任务创建等功能实现。此外,还介绍了硬件申领流程、技术资料获取渠道及开发建议,帮助开发者高效启动基于EAM2011芯片的开发工作。 适合人群:具备嵌入式系统开发经验的研发人员,特别是对RISC-V架构感兴趣的工程师和技术爱好者。 使用场景及目标:①了解EAM2011芯片的特性和应用场景,如智能汽车、智能家居和工业控制;②掌握基于EAM2011芯片的开发板和芯片的硬件资源和接口配置;③学习如何实现基本的外设驱动,如GPIO、ADC、CAN、PWM等;④通过RTOS任务创建示例,理解多任务处理和实时系统的实现。 其他说明:开发者可以根据实际需求扩展这些基础功能。建议优先掌握《EAM2011参考手册》中的关键外设寄存器配置方法,这对底层驱动开发至关重要。同时,注意硬件申领的时效性和替代方案,确保开发工作的顺利进行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值