zoukankan      html  css  js  c++  java
  • 继承(extend)

    继承(面试题)

    类与类之间的继承 三种方式

    1.原型链继承 ( extend-prototype)

    原型继承 子类的原型指向父类的实例

    <script>
           //继承 :类与类之间的继承 三种
           // 1.原型继承
         
           //父类
           function Animal(a, b) {
               //属性
               this.a = a;
               this.b = b;
          }
           Animal.prototype.say = function () {
               console.log('My name is ' + this.a)
          }
           
       
           //子类
           function Dog() {
               this.c = 5;
               this.zy = function () {
                   console.log('哈哈哈');
              }
          }
         
       
           //原型继承 子类的原型指向父类的实例  
           Dog.prototype = new Animal(1, 2);
         
       
           var snoopy = new Dog()
           console.log(snoopy); //Dog {c: 5, zy: ƒ}__proto__: Animal a: 1 b: 2
           console.log(snoopy.a) // 1
           snoopy.say() //My name is 1
           snoopy.zy()  // 哈哈哈
     
           //instanceof:运算符。判断当前对象是否是另一个对象的实例
           console.log(snoopy instanceof Dog);  //true
           console.log(snoopy instanceof Animal); //true
       </script>

    特点

    1.非常纯粹的继承关系,实例是子类的实例,也是父类的实例

    2.父类新增原型方法/原型属性,子类都能访问到

    3.简单,易于实现

    缺点

    1.要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中

    2.无法实现多继承

    3.来自原型对象的引用属性是所有实例共享的

    4.创建子类实例时,无法向构造函数传参

    2、构造继承 (call 、apply 继承) extend-constructor

    构造继承不考虑原型

    把父类的构造函数当成普通函数在子类的构造函数里调用,并且修改this指向

     <script>
           //第二种 借用继承 寄生继承
           // 父类

           function Animal(a, b) {
               this.a = a;
               this.b = b;
               this.aa = function () {
                   console.log(55);

                   return 555;
              }
          }
           Animal.prototype.say = function () {
               console.log("66")
          }
           // 子类
           function Dog(a, b) {
               this.c = 666;
               // 把父类的构造函数当成普通函数在子类的构造函数里调用,并且修改this指向
               // 这里Animal作为普通的全局函数再调用,所以里面的this指window
               // 所以希望在调用Animal的时候把this指向外层Cat的this
               // call或者apply a,b实参
               // Animal.apply(this, [ a, b ])
               Animal.call(this, a, b)
          }
           var snoopy = new Dog(1, "2");
           console.log(snoopy);
           console.log(snoopy.a); // 蓝色1
           console.log(snoopy.b);// 黑色2
           // console.log(snoopy.say());//报错 ,继承不了原型上的方法
           snoopy.aa() // 55
           console.log(snoopy.aa()); // 555
           var rr = new Animal(1, 2)
           rr.say()
           // console.log( snoopy.aa());
           console.log(snoopy instanceof Dog) // true
           console.log(snoopy instanceof Animal) // false
       </script>

    特点

    1、解决了1中,子类实例共享父类引用属性的问题

    2、创建子类实例时,可以向父类传递参数

    3、可以实现多继承(call多个父类对象)

    缺点

    1、实例并不是父类的实例,只是子类的实例

    2、只能继承父类的实例属性和方法,不能继承原型属性/方法

    3、无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

    3、组合继承(原型链和构造继承的组合) extend-group

    组合继承是原型链继承和构造继承的组合

      <script>

           // 组合继承是原型链继承和构造继承的组合
           function Animal(name) {
               this.name = name
          }
           Animal.prototype.say = function () {
               console.log('My name is ' + this.name)
          }

           function Pig(name) {
               Animal.call(this, name)
          }
           Pig.prototype = new Animal()

           var peiqi = new Pig('Peiqi')
           peiqi.say()

           var qiaozhi = new Pig('Qiaozhi')
           qiaozhi.say()

           console.log(peiqi.say === qiaozhi.say) // true

           console.log(peiqi instanceof Pig)  //true
           console.log(peiqi instanceof Animal)  //true
       </script>

    4、ES6继承(语法糖) extend-class

    extends关键字相当于实现原型链继承

    Dog.prototype = new Animal('Snoopy')

    super是ES6新增的方法,这个方法在继承子类的构造函数里调用

    相当于Animal.call(this, name, age)

      <script>
           class Animal {
               constructor (name, age) {
                   this.name = name
                   this.age = age
              }
               say () {
                   console.log(`My name is ${this.name}, I am ${this.age} years old`)
              }
          }
           // extends关键字相当于实现原型链继承
           class Mouse extends Animal {
               constructor (name, age) {
                   // super是ES6新增的方法,这个方法在继承子类的构造函数里调用
                   // 相当于Animal.call(this, name, age)
                   super(name, age)
              }
          }
           var jerry = new Mouse('Jerry', 80)
           jerry.say()

           console.log(jerry instanceof Mouse) // true
           console.log(jerry instanceof Animal) // true

       </script>

    5、静态属性

            // 静态属性 是指 只能有 构造函数调用,实例无法调用的属性
           // 不是静态属性 则只能有 实例调用,构造函数无法调用的属性
           /*
          两种写法:
              1.类内部 定义属性时 加上 static关键字
              2,在外部通过 类.属性名 = 值 定义
            */
           class Animal {
               a = 10;
               b = 20;
               c = () => {
                   console.log(11)
                   console.log(this);
              }
               d = "我是一个静态afa f属性";
               static e = () => {
                   console.log("我是静态adad方法")
              }
               p = function () {
                   console.log("bushi静态");

              }
          }
           var pig = new Animal()
           console.log(typeof Animal); // function
           console.log(typeof pig);  //object

           // Animal.e() "我是静态adad方法"
           //   pig.p() "我是adad方法"
           //   pig.e   pig.e is not a function
           // Animal.p() Animal.p is not a function

       // Animal().p() // 报错 在没有“new”的情况下无法调用类构造函数Animal
           new Animal().p() //bushi静态

    6、定义属性

    第一种方法
            // 定义属性的第一种方法
            class Animal {
               a = 10;
               b = 20;
               c = () => {
                   console.log(this, 11);
              }
          }
           var a1 = new Animal();
           console.log(a1)  //Animal {a: 10, b: 20, c: ƒ}
           a1.c();  //Animal {a: 10, b: 20, c: ƒ} 11
    第二种方法 建议使用
            class Animal {
               constructor(name, age) {
                   // 在new 类自动调用的 this指向实例
                   // 属性第二种定义方法 是在constructor中定义 建议写法
                   this.name = name;
                   this.age = age;
              }
               a() {
                   console.log(this, 1)
              }
          }
           var a2 = new Animal("小红", 20);
           console.log(a2);  // Animal {name: "小红", age: 20}
           console.log(a2.a === Animal.prototype.a)  // true
           a2.a() // Animal {name: "小红", age: 20} 1

     

  • 相关阅读:
    Spring IoC和AOP使用扩展(二)
    Spring核心概念(一)
    MyBatis的动态SQL(五)
    MyBatis的SQL映射文件(四)
    初始myBatis(三)
    初始myBatis(二)
    微信小程序学习九 事件系统
    微信小程序学习八 wxs
    微信小程序学习七 视图层wxml语法
    微信小程序学习六 模块化
  • 原文地址:https://www.cnblogs.com/lilamisu/p/13226929.html
Copyright © 2011-2022 走看看