zoukankan      html  css  js  c++  java
  • 492 js的继承:原型继承,CALL继承,寄生组合式继承,ES6中的类和继承

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
      <title>哈哈 - </title>
    </head>
    
    <body>
    </body>
    
    </html>
    <script>
      /*
       * JS本身是基于面向对象开发的编程语言
       *    => 类:封装、继承、多态 
       * 
       * 封装:类也是一个函数,把实现一个功能的代码进行封装,以此实现“低耦合高内聚”
       * 多态:重载、重写
       *    重写:子类重写父类上的方法(伴随着继承运行的)
       *    重载:相同的方法,由于参数或者返回值不同,具备了不同的功能(JS中不具备严格意义上的重载,JS中的重载:同一个方法内,根据传参不同实现不同的功能)
       * 继承:子类继承父类中的方法
       */
    
      /* 
        public void fn(int x, init y){}
        public void fn(int x){ }
    
        JavaScript中:
        fn(10, 20); 执行第一个FN
        fn(10); 执行第二个FN
        fn('哈哈'); 报错
      */
    
    
      function fn(x, y) {
        console.log(x, y)
      }
    
      function fn(x) {
        console.log(x)
      }
    
      fn(10, 20); // 执行第二个FN
      fn(10); // 执行第二个FN
    
    
      function fn(x, y) {
        if (y === undefined) {
          // ...
          return;
        }
        // ....
      }
      fn(10);
      fn(10, 20);
    </script>
    
    
    <script>
      /*
       * 在JS语言中,它的继承和其它编程语言还是不太一样的 
       * 继承的目的:让子类的实例同时也具备父类中的私有属性和公共方法
       */
    
      // JS中第一种继承方案:原型继承(让子类的原型等于父类的实例即可)
      function Parent() {
        this.x = 100;
      }
    
      Parent.prototype.getX = function getX() {
        return this.x;
      };
    
      function Child() {
        this.y = 200;
      }
    
      // => 原型继承 
      Child.prototype = new Parent;
      // console.log(Child.prototype.constructor) // 改变了Child.prototype.constructor指向:ƒ Parent() {this.x = 100;},应该重新指向Child
    
      Child.prototype.getY = function getY() {
        return this.y;
      };
    
      let c1 = new Child;
      console.log(c1); // Child {y: 200}
      console.log(c1.y); // 200
      console.log(c1.x); // 100
      console.log(c1.getY()); // 200
      console.log(c1.getX()); // 100
    
    
      // -----------------------------------
    
    
      // JS中第二种继承方式:CALL继承(只能继承父类中私有的,不能继承父类中公共的)
      function Parent() {
        this.x = 100;
      }
    
      Parent.prototype.getX = function getX() {
        return this.x;
      };
    
      function Child() {
        // 在子类构造函数中,把父类当做普通方法执行(没有父类实例,父类原型上的那些东西也就和它没关系了)
        // this -> Child的实例c1
        Parent.call(this); // this.x=100: 相当于强制给c1这个实例设置一个私有的属性x,属性值100,相当于让子类的实例继承了父类的私有的属性,并且也变为了子类私有的属性 “拷贝式”
        this.y = 200;
      }
    
      Child.prototype.getY = function getY() {
        return this.y;
      };
    
      let c1 = new Child;
      console.log(c1);
    
    
      // -----------------------------------
    
    
      // 我们满意的:父类私有的,变成子类私有的;父类公共的,变成子类公共的。
      // JS中第三种继承:寄生组合式继承(CALL继承 + 另类原型继承)
      function Parent() {
        this.x = 100;
      }
    
      Parent.prototype.getX = function getX() {
        return this.x;
      };
    
      function Child() {
        Parent.call(this);
        this.y = 200;
      }
    
      Child.prototype = Object.create(Parent.prototype);
      // 重定向了Child.prototype,重新指向Child
      Child.prototype.constructor = Child;
    
      Child.prototype.getY = function getY() {
        return this.y;
      };
    
      let c1 = new Child;
      console.log(c1);
    
    
    		// 创建一个空对象,让其原型链指向obj
      /* let obj = {
        xxx: 'xxx'
      };
      console.log(Object.create(obj)); */
    </script>
    
    <script>
      /* ES6中的类和继承 */
      class Parent {
        constructor() {
          this.x = 100;
        }
        // Parent.prototype.get X = function... ,在Parent.prototype上添加方法getX
        getX() {
          return this.x;
        }
      }
    
      // 继承: extends Parent(类似于寄生组合继承)
      // 注意:继承后,【如果子类有constructor,】一定要在constructor第一行加上super
      class Child extends Parent {
        constructor() {
          // 类似于我们之前的CALL继承。super(100,200):相当于把Parent中的constructor执行,传递了100和200
          super();
          this.y = 200;
        }
        getY() {
          return this.y;
        }
      }
    
      let c1 = new Child;
      console.log(c1);
      
      // Child(); // => Uncaught TypeError: Class constructor Child cannot be invoked without 'new' : ES6中创建的就是类,不能当做普通函数执行,只能new执行
    </script>
    

    // 补充案例
    function wjl(name, age) {
      // name、age通过参数传进来的,是每一个实例对象私有的属性。
      // height、house不是通过参数传进来的,是所有实例对象共有的属性。
      this.name = name
      this.age = age
      this.height = 188
      this.house = function () {
        return '兰博基尼'
      }
    }
    
    wjl.prototype.money = 888
    var obj = new wjl('王健林', 12) // obj是wjl的实例对象, 参数 '王健林'、12是obj这个实例对象私有的,不是wjl所有的实例对象共有,这里的 '王健林'、12 和 wsc的实例对象o 没有关系
    console.log('obj-------', obj) // wjl {name: "王健林", age: 12, height: 188, house: ƒ}
    
    function wsc(names, ages) {
      this.names = names
      this.ages = ages
      wjl.call(this) // 继承wjl,而不是wjl的实例
    }
    
    var o = new wsc('王思聪', 22, 33, 55)
    console.log('o----', o) // wsc {names: "王思聪", ages: 22, name: undefined, age: undefined, height: 188, …}
    
    // 【'王健林'、12是obj实例的私有属性,不是wjl类的所有实例继承的属性。如果在wjl类中写 this.height = 188,而不是传进来的参数,那么this.height = 188就是wjl类的所有实例继承的属性、属性值,就像wjl类的this.house。】
    console.log(o.house, o.name, o.age) // 函数 undefined undefined  
    console.log(o.house, o.names, o.ages) // 函数 王思聪 22
    
  • 相关阅读:
    风讯DotNetCMS sp5安装笔记
    datalist中实现自动编号写法
    windows server 2008 自动登录设置
    C#软件监控外部程序运行状态
    WPF启动屏幕SplashScreen
    Windows Server 2019 在桌面上显示“我的电脑”
    使用jquery的load方法加载html页面,html引入的js无效
    sql查询文章上一篇下一篇
    C#调用user32.dll Win32的API函数
    C#调用dll提示"试图加载格式不正确的程序
  • 原文地址:https://www.cnblogs.com/jianjie/p/13215735.html
Copyright © 2011-2022 走看看