JS16---js继承

子类继承父类
面向对象开发
用作高级应用

一.原型继承

原型上的属性只能是共通的 (所有的对象都有,而且值是相同的)

缺点:原型属性共享 给子类原型追加方法或属性必须在原型继承之后进行
原型继承不能实现多继承(同时继承多个对象)
优点:直接继承(比较直观) 子类的实例既是自身,也是父类

	//父类
    function Animal(name,sex){
        this.name=name||"动物";
        this.sex=sex||"性别";
        this.sleep=function(){
            return this.name+"睡觉";
        }
    }
    //子类
    function Cat(){
    }
    function Mouse(){
    }
    Cat.prototype=new Animal();  //将Animal的属性给Cat的原型链
    Cat.prototype.eat=function(){  //追加方法或属性,在原型继承之后
        return this.name+"吃饭";
    }
    //原型prototype写在new之前
    var cat=new Cat();   //实例化对象
    //cat.name="小花";  //这样写原型里边有name,外边的类对象也有name
    //全部都写成prototype继承

    Mouse.prototype=new Animal(222);  //父里边的属性子都可以使用,传参的话,在new Animal这里传参
    var mouse=new Mouse();
    var mouse1=new Mouse();

    console.log(cat);
    console.log(mouse);//mouse和mouse1输出一样
    console.log(mouse1);
    console.log(cat instanceof Cat);    //true
    console.log(cat instanceof Animal); //true
    //缺点:原型属性共享   给子类原型追加方法或属性必须在原型继承之后进行
    //原型继承不能实现多继承(同时继承多个对象)
    //优点:直接继承(比较直观) 子类的实例既是自身,也是父类

实例中存在和原型对象上同名的属性时,会自动屏蔽原型对象上的同名属性
只会在实例上创建一个同名的本地属性。

    //父类:人
    function Person () {
      this.head = '脑袋瓜子';
    }
    //子类:学生,继承了“人”这个类
    function Student(studentID) {
      this.studentID = studentID;
    }
    Student.prototype = new Person();

    var stu1 = new Student(1001);
    console.log(stu1.head); //脑袋瓜子

    stu1.head = '聪明的脑袋瓜子';
    console.log(stu1.head); //聪明的脑袋瓜子
    
    var stu2 = new Student(1002);
    console.log(stu2.head); //脑袋瓜子

原型上任何类型的属性值都不会通过实例被重写,但是引用类型的属性值会受到实例的影响而修改。

二.构造继承

在子类的构造函数中,通过 apply () 或 call ()的形式,调用父类构造函数,以实现继承。
优点:在创建子类的实例的时候可以向父类传参
可以实现多继承
子类的实例只能是自身

call apply 对象里边的this替换
参数   1.替换的对象   2.参数列表
call(this,1,2,3,4,5) 序列参数列表  apply(this,[1,2,3,4,5])  集合
 //两个父类,多继承
   function Animal(name,sex){
        this.name=name||"动物";
        this.sex=sex||"性别";
        this.sleep=function(){
            return this.name+"睡觉";
        }
    }
    function Type(type){
        this.type=type||"类别";
    }
    //子类
    function Cat(name,sex,type){
        Animal.call(this,name,sex);  //这个this就是animal里边的this,相当于将Animal的东西全部复制过去
        Type.apply(this,[type]);
        this.eat=function(){
            return this.name+"爱吃老鼠";
        }
    }
    function Mouse(){

    }
    var cat=new Cat("小黑","公","猫科");
    var cat1=new Cat("小百","母","狗科");
    console.log(cat);
    console.log(cat1);
    console.log(cat instanceof Cat);     //true
    console.log(cat instanceof Animal);  //false

    //优点:在创建子类的实例的时候可以向父类传参   可以实现多继承
    //子类的实例只能是自身

三.组合继承 原型+构造

可以实现多继承
子类的实例既是自身也是父类
数据共享

    function Animal(name,sex){
        this.name=name||"动物";
        this.sex=sex||"性别";
        this.sleep=function(){
            return this.name+"睡觉";
        }
    }
    function Type(type){
        this.type=type||"类别";
    }
    function Cat(type){     //构造继承
        Type.call(this,type);
    }
    Cat.prototype=new Animal();  //原型继承
    Cat.prototype.name="小花";

    var cat=new Cat(123);
    console.log(cat);
    console.log(cat instanceof Cat)
    console.log(cat instanceof Animal)

四.实例继承

子类对象中实例化父类,然后返回父类
最大优点:不会限制我们的执行方法,可以直接new,也可以直接调用
缺点:子类的实例不是本身,而是父类; 不可以实现多继承

    //父类
  function Animal(name,sex){
        this.name=name||"动物";
        this.sex=sex||"性别";
        this.sleep=function(){
            return this.name+"睡觉";
        }
     }
     //子类
     function Cat(name,sex){
         this.eat="fdghghdhas";  //里边并不会出现eat属性,不可以这样追加属性。
         var animal=new Animal(name,sex);//追加属性,只能在父类中追加属性
         return animal;   //方法里边返回对象
     }
    var cat=new Cat("123","111");
    console.log(cat);  //Animal {name: "123", sex: "111", sleep: ƒ}
    console.log(cat instanceof Cat);   //false
    console.log(cat instanceof Animal); //true   缺点:子类的实例不是本身,而是父类; 不可以实现多继承

    var cat1=Cat("xnn","jsjj");
    console.log(cat1);//Animal {name: "xnn", sex: "jsjj", sleep: ƒ}
    //最大优点:不会限制我们的执行方法,可以直接new,也可以直接调用

五.组合寄生

构造+原型+寄生 = 组合寄生模式(好几个模式组到一起再加一个寄生)
继承的时候原型追加的方法继承不到,若是想用这个方法,只能把原型对象的方法寄生到某个东西上

Super的原型属性没办法直接继承,只能间接性的给到某一个对象的属性上,然后再通过继承,就可以用原型属性了

    function Super(b){
   		 this.b=b;
   		 this.fun=function(){}
    }
    //给Super追加底层方法
    Super.prototype.c=function(){
        console.log(1);
    }//继承的时候原型追加的方法继承不到,若是想用这个方法,只能把原型对象的方法寄生到某个东西上
    function f1(){

    }
    var f=new f1();//将底层方法分离出来
    f.prototype=Super.prototype;  //将Super的原型对象寄生到f1的原型上,f1相当于一个桥

    function Foo(a,b){
        this.a=a;
        Super.call(this,b);//构造继承
    }
    Foo.prototype=f;
    var foo1=new Foo(1,2);
    console.log(foo1);
     console.log(foo1.prototype.c());   //会输出undefined,因为这个方法没有返回值
    // console.log(foo1.c());   //不能直接点c,要加prototype,因为c方法在原型上

先new再寄生原型:原型方法和属性在prototype中
(先new再寄生原型:相当于给f1添加原型链)
先寄生再new原型:原型方法和属性可以直接点出来
(c方法会跑到Object原型链上,原因:f1的原型链往下直接指向Object,Object中才有prototype)

    function Super(b){
    this.b=b;
    this.fun=function(){}
    }
    Super.prototype.c=function(){
        console.log(1);
    }
    function f1(){

    }
    f1.prototype=Super.prototype; 
    var f=new f1();

    function Foo(a,b){
        this.a=a;
        Super.call(this,b);
    }
    Foo.prototype=f;
    var foo1=new Foo(1,2);
    console.log(foo1);
    console.log(foo1.c());   

六.寄生模式

继承时有些模式 拿不到原型的一些方法和属性,考虑寄生
原型继承,父类添加的原型可以获取到

function Animal(name,sex){
    this.name=name;
    this.sex=sex;
    this.eat=function(){
        return this.name+"啥都吃";
    }
}

function Cat(){

}
Cat.prototype=new Animal("小花","女");  //给Animal里边的属性赋值,在Animal这里传参
原型继承,父类里边的内容都是共享的
Animal.prototype.like=function(){
    return "躺床上";
}
var cat=new Cat();
console.log(cat);
console.log(cat.like());
//Cat {}
__proto__: Animal
eat: ƒ ()
name: "小花"
sex: "女"
__proto__:
like: ƒ ()           //在Object原型链上,Animal没被new之前,Animal原型链直接指向Object
constructor: ƒ Animal(name,sex)
__proto__: Object

构造继承,父类方法的原型方法继承不到
若想拿到外边的要考虑寄生

function Animal(name,sex){
    this.name=name;
    this.sex=sex;
    this.eat=function(){
        return this.name+"啥都吃";
    }
}

function Cat(name,sex){
    Animal.call(this,name,sex);
}
Animal.prototype.like=function(){
    return "躺床上";
}
var cat=new Cat("小花","女");
console.log(cat);//构造继承,原型追加的属性无法获得

//Cat {name: "小花", sex: "女", eat: ƒ}
eat: ƒ ()
name: "小花"
sex: "女"
__proto__:
constructor: ƒ Cat(name,sex)
__proto__: Object

添加寄生继承后,父类的原型子类就可以获取到了
只是构造模式的继承

function Animal(name,sex){
    this.name=name;
    this.sex=sex;
    this.eat=function(){
        return this.name+"啥都吃";
    }
}
Animal.prototype.like=function(){
    console.log(this);   //这里边的this指得是Animal.prototype原型链
    return this.name+ "躺床上";
}

function Cat(name,sex){
    Animal.call(this,name,sex);
}

var cat=new Cat("小花","女");
cat.likeele=Animal.prototype;  //原型添加到一个属性上
console.log(cat);
console.log(cat.likeele.like.call(cat));//用cat里边的this替换Animal.prototype原型里边的this

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值