ES5和ES6中的继承详细介绍 原型介绍

原型

function Fn(){

}
Fn.prototype.play = fuciton(){

}//prototype 就是这个函数的原型 给原型上添加方法就相当于ES6中的静态方法
var a = new Fn();
console.log(f)//当实例化构造函数时,实例化会将构造函数的prototype对象下的所有方法和属性添加在实例化对象的原型链中
function Box(){

}
Box.prototype = {
   a:1,
   run:function(){},
   play:function(){}
}//如果直接用等号赋值的话,会出现一些问题,你会发现类中的原型上的constructor没有了,此时还需要在加上constructor,如果原本类中还有别的方法也会被替换掉,所以尽量不要使用这种方式。
 Object.defineProperty(Box.prototype,"constructor",{
     value:Box
 })//当给Box这个类的原型上加入了数据后,在给他加上constructor属性

当我们实例化对象这个Box时,实例化对象的原型链就等同于类的原型

var b=new Box();
console.log(b);//实例化对象中的原型链就和父类中的原型是等同的
console.log(Box.prototype===b.__proto__)//true

使用原型的好处在于当你需要给某一类添加方法时,可以直接给某一类上的这个原型上直接加一个方法,就方便我们调用和使用。例如我想给div这一个类加一个方法,这样的话我所有的div都可以使用

  var div0 = document.querySelector(".div0");
  var div1 = document.querySelector(".div1");
       div0.setBg=function(){
             this.style.width="100px",
             this.style.height="50px";
             this.style.backgroundColor="red";
         } //只给div0设置就只有div0有这个方法,其他div无法使用
        HTMLDivElement.prototype.setBg=function(){
             this.style.width="100px",
             this.style.height="50px";
             this.style.backgroundColor="red";
         }//给所有div类添加方法,此时所有div均可调用
         div0.setBg();
         div1.setBg(); 

也可以使用 Object.defineProperties来给某一类的原型中追加方法,

Object.defineProperties(HTMLDivElement.prototype, {
            width: {
                set: function (value) {
                    this.style.width =value + "px";
                },
                get: function () {
                    return parseFloat(getComputedStyle(this).width);
                }
            },
            height: {
                set: function (value) {
                    this.style.height = value + "px";
                },
                get: function () {
                    return parseFloat(getComputedStyle(this).height);
                }
            },
            bgColor: {
                set: function (_v) {
                    this.style.backgroundColor = (typeof _v === "string") ? _v : "#" + _v.toString(16)
                        .padStart(6, "0");
                },
                get: function () {
                    return parseFloat(getComputedStyle(this).backgroundColor);
                }
            },

利用原型重构Array的some方法

Array.prototype.some1=function(fn){
    for(var i=0;i<this.length;i++){
        if(fn(this[i],i,this)) return true;
       }
     return false;
   }

在原型上我们可以添加或者更改某一便于我们使用的方法,它可以给某一类添加,更方便我们的代码执行。

继承

ES6的继承

在ES6中继承可以直接使用extends

 class A {
        constructor() {
        }
        run() {
            console.log("a");
        }
        play(){
            console.log('b')
        }
      }

      class B extends A {
        constructor() {
          super();//继承时一定要写入super()
        }
        run(){
            super.run();
            console.log("c");
        }
      }
  let b = new B();//此时实例化对象b也具有A类的方法
ES5的继承

ES5中的继承是将某一类的实例化对象复制给某一类的原型来达到继承

function Box(){
      
 }
Box.prototype.run=function(){

 }   
Box.prototype.a=10;
 function Ball(){
     
 }
 Ball.prototype=new Box();//用这个方法来实现继承,但是此时他的原型中的constructor丢失,所以要重新追加,使用下面的方式
 Object.defineProperty(Ball.prototype,"constructor",{
       value:Ball
   })

这样看上去没又任何问题,但是一旦传入参数是就会又问题,当我传入参数时,没有办法给Box这个构造函数传参,打印的结果就会为undefined.

function Box(b){
      this.a=a;
      console.log(b)
 }
Box.prototype.run=function(){

 }   
Box.prototype.a=10;
 function Ball(b){
     
 }
 Ball.prototype=new Box();
 Object.defineProperty(Ball.prototype,"constructor",{
       value:Ball
   })
冒充继承

此时我们需要修改Box中 的this指向,只需要在Ball这个构造函数中加入下面语句。

 function Ball(b){
    Box.call(this,b);
  }

这个时候我们修改了Box中的this指向,当前this为实例化对象Ball的对象,这样我们就可以进行传参,这个语句就相当于ES6中的super一样。我们成这种方式为冒充继承。

寄生式继承

但是这种方式也有问题,就是当你创建一个实例化对象时,他会运行Box这个构造函数种的内容,我们一般情况下需要它继承,但是又不想让他执行这个函数体,此时我们又有了一种方式,我们称它为寄生式继承。

寄生式继承的方式就是你在新建一个和你需要继承类一摸一样的类,不过在它这个构造函数种什么都不写,只复制你需要继承类的原型 ,然后在使用继承 。

function Box(b){
            this.b=b;
            console.log(b);
     }
        Box.prototype.run=function(){

      }
        Box.prototype.a=10;
function F(){

     }//创建一个新的类
        F.prototype=Box.prototype;//复制原型

        function Ball(b){
            Box.call(this,b);
        }
        Ball.prototype=new F();//继承给Ball这个类
        Object.defineProperty(Ball.prototype,"constructor",{
            value:Ball
        })

使用这种写法就达到了我们所需要的目的。

ES5继承的封装

使用寄生继承

Function.prototype.extend = function (superClass) {
        function F() {}
        F.prototype = superClass.prototype;//复制需要继承原型
         var proto = this.prototype;//保留当前类中的原型上的方法,属性
         this.prototype = new F();//继承完后然后在追加之前的原型上的数据
         var names = Object.getOwnPropertyNames(proto);
         for (var i = 0; i < names.length; i++) {
           var desc = Object.getOwnPropertyDescriptor(proto, names[i]);
           Object.defineProperty(this.prototype, names[i], desc);
        }
         Object.defineProperty(this.prototype, "constructor", {
          value: this,
       });//防止当前类的原型上的constructor丢失
       //后面的代码是为了保证继承的原型上的数据没有任何问题来判断的
         this.prototype.superClass = superClass;
         if (superClass.prototype.constructor !== superClass) {
          Object.defineProperty(superClass.prototype, "constructor", {
             value: superClass,
          });
         }
       };

使用时直接调用就可以使用

function Box(b) {
      this.b = b;
      console.log(b);
   }
    Box.prototype.run = function () {
           console.log("a");
      };
      Box.prototype.a = 10;

     function Ball(b) {
         this.superClass.apply(this,arguments);//修改继承类种的this指向
    }
   Ball.prototype.play=function(){

    }
 Ball.extend(Box);//直接调用就可以
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值