美文网首页
es6中的类(五)

es6中的类(五)

作者: 未路过 | 来源:发表于2022-09-15 13:12 被阅读0次

    1. 认识类

    64.PNG
    // 类的声明
    class Person {
    
    }
    
    // babel
    
    
    
    // 类的表达式(用的比较少)
    // var Animal = class {
    // }
    
    
    // 研究一下类的特性
    console.log(Person.prototype)
    console.log(Person.prototype.__proto__)
    console.log(Person.prototype.constructor)
    console.log(typeof Person) // function
    
    var p = new Person()
    console.log(p.__proto__ === Person.prototype) // true
    
    //总结
    /* 
    
    class Person{
    
    }
    就是 function Person(){
    
    }
    构造函数的语法糖。
    

    2. class的构造方法

    // 类的声明
    class Person {
      // 类的构造方法
      // 注意: 一个类只能有一个构造函数,这个构造函数在new的时候就会被调用,然后按照以下步骤进行运行
      // 1.在内存中创建一个对象 moni = {}
      // 2.将类的原型prototype赋值给创建出来的对象 moni.__proto__ = Person.prototype
      // 3.将对象赋值给函数的this: new绑定 this = moni
      // 4.执行函数体(构造函数constructor)中的代码
      // 5.如果构造函数没有返回非空对象,则返回创建出来的新对象;
      constructor(name, age) {
        this.name = name
        this.age = age
      }
    }
    
    
    var p1 = new Person("why", 18)
    var p2 = new Person("kobe", 30)
    console.log(p1, p2)
    
    

    3. JavaScript 对象访问器(补充)

    ECMAScript 5 (2009) 引入了 Getter 和 Setter。

    JavaScript Getter(get 关键词)
    //本例使用 lang 属性来获取 language 属性的值。
    // 创建对象:
    var person = {
      firstName: "Bill",
      lastName : "Gates",
      language : "en",
      get lang() {
        return this.language;
      },
      set lang(newLang) {
        console.log('setting lang');
        this.language = newLang;
      }
    };
    
    console.log(person.lang);//en
    //意味着不对langeuage直接进行操作,而是通过lange这个方法进行对language的操作
    person.lang = "CN";
    console.log(person.lang);//CN
    

    优点1:提供更简洁的语法

    下面两个例子的区别在哪里?

    例子 1

    var person = {
      firstName: "Bill",
      lastName : "Gates",
      fullName : function() {
        return this.firstName + " " + this.lastName;
      }
    };
    
    // 使用方法来显示来自对象的数据:
    document.getElementById("demo").innerHTML = person.fullName();
    

    例子 2

    var person = {
      firstName: "Bill",
      lastName : "Gates",
      get fullName() {
        return this.firstName + " " + this.lastName;
      }
    };
    
    // 使用 getter 来显示来自对象的数据:
    document.getElementById("demo").innerHTML = person.fullName;
    

    例子 1 以函数形式访问 fullName:person.fullName()。

    例子 2 以属性形式访问 fullName:person.fullName。

    第二个例子提供了更简洁的语法。

    优点2: 提高数据质量

    使用 getter 和 setter 时,JavaScript 可以确保更好的数据质量。

    在本例中,使用 lang 属性以大写形式返回 language 属性的值:

    // Create an object:
    var person = {
      firstName: "Bill",
      lastName : "Gates",
      language : "en",
      get lang() {
        return this.language.toUpperCase();
      }
    };
    
    // 使用 getter 来显示来自对象的数据:
    document.getElementById("demo").innerHTML = person.lang;
    

    4.class中的方法定义

    var names = ["abc", "cba", "nba"];
    class Person{
      constructor(name, age){
        this.name = name;
        this.age = age;
        this._address = "广州市";
      }
    
      //这里的eating和running,还有get和set本质上就是放在Person的prototype上的
    //console.log(Object.getOwnPropertyDescriptors(Person.prototype))
    
      eating(){
        console.log(this.name + "eating");
      }
    
      runnning(){
        console.log(this.name + "running");
      }
    
      //类的访问器方法
      get address(){
        console.log("访问器拦截操作");
        return this._address
      }
    
      set address(newAddress){
        console.log("拦截设置操作");
        this._address = newAddress;
      } 
    
        //以上eating和runnning是通过创建实例对象,让实例对象进行访问,比如var p = new Person() p.eating() 
    //访问器方法也是通过实例对象去访问的 
        
      //类的静态方法(类方法) ,不需要去创建实例对象,通过类名直接去访问
      // Person.createPerson()
      //静态方法通常用于定义直接使用类来执行的方法,不需要有类的实例,使用static关键字来定义:
    //静态方法不会被实例继承
    
      static randomPerson(){
        var nameIndex = Math.floor(Math.random()* names.length);
        var name = names[nameIndex];
        var age = Math.floor(Math.random()*100);
        return new Person(name, age)
      }
    }
    
    var p = new Person("why", 18);
    p.eating();
    p.runnning();
    
    console.log(p.address)
    p.address = "北京市"
    console.log(p.address)//北京市
    
    var p1 = Person.randomPerson();//我们想创建出来一个对象,但是名字和年龄都是随机出来的
    console.log(p1);
    for (var i = 0; i < 50; i++) {
      console.log(Person.randomPerson())//创建出来50个person对象
    }
    

    5 class中实现继承extends

    1.1.父类属性的继承(super)

    class Person {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
    }
    
    // Student称之为子类(派生类)
    /* class Student extends Person {
      constructor(name, age, sno) {
        this.name = name;
        this.age = age;
        this.sno = sno
      }
    
    } */
    
    //会报错
    //test.html:60 Uncaught ReferenceError: Must call super constructor in derived class before accessing
    // 'this' or returning from derived constructor
    //子类必须调用父类的构造方法
     // JS引擎在解析子类的时候就有要求, 如果我们有实现继承
    //那么子类在子类的构造方法中, 在使用this之前,需要调用父类的构造方法
      //使用super关键字
    
    
      class Student extends Person {
      constructor(name, age, sno) {
        super(name, age)
        this.sno = sno
      }
    
    }
    
    var stu = new Student("why", 18, 111);
    console.log(stu);
    //Student {name: 'why', age: 18, sno: 111}
    

    如果子类没有自己的构造函数

    class Person {
            constructor(name, age) {
              this.name = name;
              this.age = age;
            }
          }
    
          class Student extends Person {}
    
          var stu = new Student("why", 18);
          console.log(stu);
          //Student {name: 'why', age: 18}
          //如果子类没有定义constructor()方法,这个方法会默认添加,
    //并且里面会调用super()。也就是说,不管有没有显式定义,任何一个子类都有constructor()方法。
          class Student extends Person {}
    
          // 等同于
          class Student extends Person {
            constructor(...args) {
              super(...args);
            }
          }
    
    67.PNG

    2. 父类原型方法的继承

    class Person {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      running() {
        console.log(this.name + " running~")
      }
    
      eating() {
        console.log(this.name + " eating~")
      }
    
    }
    
      class Student extends Person {
      constructor(name, age, sno) {
        super(name, age)
        this.sno = sno
      }
      studying() {
        console.log(this.name + " studying~")
      }
    
    }
    
    var stu = new Student("why", 18, 111);
    console.log(stu);
    //Student {name: 'why', age: 18, sno: 111}
    stu.studying();
    stu.running();
    stu.eating();
    
    //在这里,studing是在Student的原型对象上的,running和eating是在Person的原型对象上的。
    console.log(Object.getOwnPropertyDescriptors(stu.__proto__))//{constructor: {…}, studying: {…}}
    console.log(Object.getOwnPropertyDescriptors(stu.__proto__.__proto__))//{constructor: {…}, running: {…}, eating: {…}}
    //Student的原型对象的__proto—__指向Person的原型对象
    console.log(Student.prototype.__proto__ === Person.prototype);//ture
    console.log(stu.__proto__.__proto__ === Person.prototype);//ture
    

    3. 子类对父类原型方法的重写

    情况1:重写

    class Person {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      running() {
        console.log(this.name + " running~")
      }
    
      eating() {
        console.log(this.name + " eating~")
      }
    
    }
    
      class Student extends Person {
      constructor(name, age, sno) {
        super(name, age)
        this.sno = sno
      }
      studying() {
        console.log(this.name + " studying~")
      }
    
       // 类对父类的方法的重写
       running() {
        console.log("student " + this.name + " running")
      }
    
    }
    
    var stu = new Student("why", 18, 111);
    console.log(stu);
    //如果子类不满意父类的running方法,可以在自己里面重新实现running方法
    //到时候就会优先找自己的,而不是父类里面的
    
    stu.running();//student why running
    

    情况2:基于父类的逻辑重写

    比如父类有下面一个方法

      personMethod() {
        console.log("处理逻辑1")
        console.log("处理逻辑2")
        console.log("处理逻辑3")
      }
    

    但是子类基于这个方法还有更多的逻辑

    personMethod() {
        console.log("处理逻辑1")
        console.log("处理逻辑2")
        console.log("处理逻辑3")
        console.log("处理逻辑4")
        console.log("处理逻辑5")
        console.log("处理逻辑6")
      }
    

    这时候完全像上面一样重写的话,就会出现重复代码,没有必要

    这时候就需要使用super的第二个用法:

    在子类的实例方法里面调用父类的方法

     // 重写personMethod方法
      personMethod() {
        // 复用父类中的处理逻辑
        super.personMethod()
    
        console.log("处理逻辑4")
        console.log("处理逻辑5")
        console.log("处理逻辑6")
      }
    

    整体代码:

    class Person {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      running() {
        console.log(this.name + " running~")
      }
    
      eating() {
        console.log(this.name + " eating~")
      }
      personMethod() {
        console.log("处理逻辑1")
        console.log("处理逻辑2")
        console.log("处理逻辑3")
      }
    
    }
    
      class Student extends Person {
      constructor(name, age, sno) {
        super(name, age)
        this.sno = sno
      }
      studying() {
        console.log(this.name + " studying~")
      }
    
       // 重写personMethod方法
       personMethod() {
        // 复用父类中的处理逻辑
        super.personMethod()
    
        console.log("处理逻辑4")
        console.log("处理逻辑5")
        console.log("处理逻辑6")
      }
    
    }
    
    var stu = new Student("why", 18, 111);
    console.log(stu);
    
    stu.personMethod();
    /* 
    处理逻辑1
    test.html:64 处理逻辑2
    test.html:65 处理逻辑3
    test.html:84 处理逻辑4
    test.html:85 处理逻辑5
    test.html:86 处理逻辑6
    */
    

    4.静态方法的继承

    class Person {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      running() {
        console.log(this.name + " running~")
      }
    
      eating() {
        console.log(this.name + " eating~")
      }
    
      static staticMethod() {
        console.log("PersonStaticMethod");
      }
    
    }
    
      class Student extends Person {
      constructor(name, age, sno) {
        super(name, age)
        this.sno = sno
      }
    
     
    
    }
    
    var stu = new Student("why", 18, 111);
    
    //调用Person的静态方法
    Student.staticMethod();//PersonStaticMethod
    

    5.子类对父类静态方法的重写

    情况1:完全重写

    class Person {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      running() {
        console.log(this.name + " running~")
      }
    
      eating() {
        console.log(this.name + " eating~")
      }
    
      static staticMethod() {
        console.log("PersonStaticMethod")
      }
    
    }
    
      class Student extends Person {
      constructor(name, age, sno) {
        super(name, age)
        this.sno = sno
      }
    
        // 重写静态方法
        static staticMethod() {
        console.log("StudentStaticMethod")
      }
    }
    
    var stu = new Student("why", 18, 111);
    
    var p = new Person();
    console.log(Person.hasOwnProperty("name")); //true
    
    //调用Person的静态方法
    Student.staticMethod();//StudentStaticMethod
    

    情况2:基于父类的重写

    class Person {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      running() {
        console.log(this.name + " running~")
      }
    
      eating() {
        console.log(this.name + " eating~")
      }
    
      static staticMethod() {
        
        console.log("PersonStaticMethod")
      }
    
    }
    
      class Student extends Person {
      constructor(name, age, sno) {
        super(name, age)
        this.sno = sno
      }
    
        // 重写静态方法
        static staticMethod() {
        super.staticMethod()
        console.log("StudentStaticMethod")
      }
    
     
    
    }
    
    var stu = new Student("why", 18, 111);
    
    //调用Person的静态方法
    Student.staticMethod();
    //PersonStaticMethod
    //StudentStaticMethod
    

    6. ES6转ES5的代码

    Babel · The compiler for next generation JavaScript (babeljs.io)
    Babel · The compiler for next generation JavaScript (babeljs.io)

    IE:Edge 15可以支持 96% 的 ES6 新特性。Edge 14 可以支持 93% 的 ES6 新特性。(IE7~11 基本不支持 ES6)

    es5

    class Person{}
    

    es5

    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
      }
    }
    
    var Person = function Person() {
      "use strict";
    //检查this是不是Person创建出来的,
    //是的话,那么就可以用instanceof来判断,instanceof就是判断某个对象是不是另一个对象的实例
      _classCallCheck(this, Person);
    };
    
    //_classCallCheck的作用就是不让你把Person当成一个普通的函数去调用它
    //比如Person() 这种情况下this是window或者undifined
    //而是希望new Person()
    
    

    es6

    class Person{
      constructor(name, age){
        this.name = name;
        this.age = age;
      }
      eating(){
        console.log(this.name + "eating")
      }
    }
    

    es5

    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
      }
    }
    
    function _defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        //获取当前对象
        var descriptor = props[i];
        //console.log(descriptor);//{key: 'eating', value: ƒ}
        //console.log(descriptor.enumerable);//undefined
        
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
       //console.log(descriptor);
          /* configurable: true
          enumerable: false
          key: "eating"
          value: ƒ eating()
          writable: true */
      }
    }
    
    /*
    
      相当于给Person.prototype里面加入eating方法
    */
    
    function _createClass(Constructor, protoProps, staticProps) {
         //如果是构造函数的话,直接给Person.prototype添加属性。
      if (protoProps) _defineProperties(Constructor.prototype, protoProps);
        //如果是构造函数的话,直接给Person添加方法。
      if (staticProps) _defineProperties(Constructor, staticProps);
      return Constructor;
    }
    
    //在这里,为什么要使用立即执行函数呢?两个原因
    //1.它可以独立创建一个作用域,不会污染到全局,每个立即执行函数内的变量都是局部变量,不会有命名冲突的情况。
    //2.方便进行进行tree-shaking处理
    //标记这个函数为纯函数/*#__PURE__*/--》没有副作用
    //纯函数被webpack做压缩的时候,是要做tree-shaking处理
    //到时候对代码进行压缩的时候,发现这个函数没有被用过,在tree-shaking的时候,进行优化,直接删除掉这些代码,打包出来的包size小
    var Person = /*#__PURE__*/ (function () {
      "use strict";
    
      function Person(name, age) {
        _classCallCheck(this, Person);
    
        this.name = name;
        this.age = age;
      }
    
      _createClass(Person, [
        {
          key: "eating",
          value: function eating() {
            console.log(this.name + "eating");
          }
        }
      ]);
    
      return Person;
    })();
    
    

    8.7 es6转es5的继承的代码

    es6

    class Person{
      constructor(name, age){
        this.name = name;
        this.age = age;
      }
    
      running(){
        console.log(this.name + " runnning");
      }
    }
    
    class Student extends Person{
      constructor(name, age, sno){
        super(name, age);
        this.sno = sno;
      }
      studying(){
        console.log(this.name + " studying");
      }
    
    
    }
    
    

    es5

    
    function _typeof(obj) {
      "@babel/helpers - typeof";
      if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
        _typeof = function _typeof(obj) {
          return typeof obj;
        };
      } else {
        _typeof = function _typeof(obj) {
          return obj &&
            typeof Symbol === "function" &&
            obj.constructor === Symbol &&
            obj !== Symbol.prototype
            ? "symbol"
            : typeof obj;
        };
      }
      return _typeof(obj);
    }
    
    function _inherits(subClass, superClass) {
      if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function");
      }
      subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: { value: subClass, writable: true, configurable: true }
      });
    
      /* 这里的目的是让Student.__proto__ = Person 
    为了实现静态方法的继承
    比如Student.staticMethod()
    这里staticMathod没有在Student对象里面,
    我们就要去Student.__proto__里面去找
    Student.__proto__默认指的是Function.prototype,但是Function.prototype里面也没这个方法
    我们就通过Student.__proto__ = Person , 这里Person里面有这个方法
    */
      if (superClass) _setPrototypeOf(subClass, superClass);
    }
    
    
    function _setPrototypeOf(o, p) {
      _setPrototypeOf =
        Object.setPrototypeOf ||
        function _setPrototypeOf(o, p) {
          o.__proto__ = p;
          return o;
        };
      return _setPrototypeOf(o, p);
    }
    
    function _createSuper(Derived) {
      var hasNativeReflectConstruct = _isNativeReflectConstruct();
      return function _createSuperInternal() {
        var Super = _getPrototypeOf(Derived),
          result;
        if (hasNativeReflectConstruct) {
          var NewTarget = _getPrototypeOf(this).constructor;
          result = Reflect.construct(Super, arguments, NewTarget);
        } else {
          result = Super.apply(this, arguments);
        }
        return _possibleConstructorReturn(this, result);
      };
    }
    
    function _possibleConstructorReturn(self, call) {
      if (call && (_typeof(call) === "object" || typeof call === "function")) {
        return call;
      } else if (call !== void 0) {
        throw new TypeError(
          "Derived constructors may only return object or undefined"
        );
      }
      return _assertThisInitialized(self);
    }
    
    function _assertThisInitialized(self) {
      if (self === void 0) {
        throw new ReferenceError(
          "this hasn't been initialised - super() hasn't been called"
        );
      }
      return self;
    }
    
    function _isNativeReflectConstruct() {
      if (typeof Reflect === "undefined" || !Reflect.construct) return false;
      if (Reflect.construct.sham) return false;
      if (typeof Proxy === "function") return true;
      try {
        Boolean.prototype.valueOf.call(
          Reflect.construct(Boolean, [], function () {})
        );
        return true;
      } catch (e) {
        return false;
      }
    }
    
    function _getPrototypeOf(o) {
      _getPrototypeOf = Object.setPrototypeOf
        ? Object.getPrototypeOf
        : function _getPrototypeOf(o) {
            return o.__proto__ || Object.getPrototypeOf(o);
          };
      return _getPrototypeOf(o);
    }
    
    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
      }
    }
    
    function _defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
      }
    }
    
    function _createClass(Constructor, protoProps, staticProps) {
      if (protoProps) _defineProperties(Constructor.prototype, protoProps);
      if (staticProps) _defineProperties(Constructor, staticProps);
      return Constructor;
    }
    
    var Person = /*#__PURE__*/ (function () {
      "use strict";
    
      function Person(name, age) {
        _classCallCheck(this, Person);
    
        this.name = name;
        this.age = age;
      }
    
      _createClass(Person, [
        {
          key: "running",
          value: function running() {
            console.log(this.name + " runnning");
          }
        }
      ]);
    
      return Person;
    })();
    
    var Student = /*#__PURE__*/ (function (_Person) {
      "use strict";
    
      _inherits(Student, _Person);
      /* 
      
      和以前寄生时候实现的方法是一样的,让Student继承Person
    
    function inheritPrototype(SubType, SuperType) {
        SubType.prototype = Object.create(SubType.prototype);
        Object.defineProperty(SuperType.prototype, "constructor", {
          enumerable: false,
          configurable: true,
          writable: true,
          value: SubType
        })
      }
    
      */
    
      var _super = _createSuper(Student);
    
      function Student(name, age, sno) {
        var _this;
    
        //以前直接Person.call(this, name, age, friend)来实现的
        //但是Person不能直接调用Person()在es6里面
        _classCallCheck(this, Student);
    
        _this = _super.call(this, name, age);
        _this.sno = sno;
        return _this;
      }
    
      _createClass(Student, [
        {
          key: "studying",
          value: function studying() {
            console.log(this.name + " studying");
          }
        }
      ]);
    
      return Student;
    })(Person);
    
    
    // Super: Person
    // arguments: ["why", 18]
    // NewTarget: Student
    // 会通过Super创建出来一个实例, 但是这个实例的原型constructor指向的是NewTarget
    // 会通过Person创建出来一个实例, 但是这个实例的原型constructor指向的Person
    //Reflect.construct(Super, arguments, NewTarget);
    
    

    8.8 继承内置类

    我们也可以让我们的类继承自内置类,比如Array

    // class Person {
    
    // }
    
    // class Student extends Person {
    
    // }
    
    class HYArray extends Array {
      firstItem() {
        return this[0]
      }
    
      lastItem() {
        return this[this.length-1]
      }
    }
    
    var arr = new HYArray(1, 2, 3)
    console.log(arr.firstItem())//1
    console.log(arr.lastItem())//3
    

    8.9 类的混入mixin

    JavaScript的类只支持单继承:也就是只能有一个父类

    1. 那么在开发中我们我们需要在一个类中添加更多相似的功能时,应该如何来做呢?
    2. 这个时候我们可以使用混入(mixin);
    class Person {
    
    }
    
    /* class Runner{
    running(){
    
    }
    }
    
    */
    function mixinRunner(BaseClass) {
      class NewClass extends BaseClass {
        running() {
          console.log("running~")
        }
      }
      return NewClass
    }
    
    
    // 在JS中类只能有一个父类: 单继承
    class Student extends Person {
    
    }
    
    var NewStudent = mixinRunner(Student)
    var ns = new NewStudent()
    ns.running()//running~
    
    68.PNG

    混入两个类

    class Person {
    
    }
    
    /* class Runner{
    running(){
    
    }
    }
    
    class Eater{
    eatting(){
    
      }
    
    } */
    function mixinRunner(BaseClass) {
      class NewClass extends BaseClass {
        running() {
          console.log("running~")
        }
      }
      return NewClass
    }
    
    function mixinEater(BaseClass) {
      return class extends BaseClass {
        eating() {
          console.log("eating~")
        }
      }
    }
    
    // 在JS中类只能有一个父类: 单继承
    class Student extends Person {
    
    }
    
    var NewStudent = mixinEater(mixinRunner(Student))
    var ns = new NewStudent()
    ns.running()
    ns.eating()
    
    

    弊端:以上方法没办法混入属性,或者在构造函数内传入一些参数

    10 JavaScript中的多态

    69.PNG
    // 传统的面向对象多态是有三个前提:
    // 1> 必须有继承(是多态的前提)
    // 2> 必须有重写(子类重写父类的方法),如果不重写,调用的都是父类的getArea()(同一种行为),认为是没有多态的体现的。重写的话,传入r的情况,调入的是Rectangle类里面的getArea()方法,
    //传入c的情况下,调用的是Circle类里面的getArea()方法,
    //这样,就可以认为不同的数据类型执行同一个操作时, 如果表现出来的行为(形态)不一样,
    // 3> 必须有父类引用指向子类对象
    
    // Shape形状
    class Shape {
      getArea() {}
    }
    
    class Rectangle extends Shape {
      getArea() {
        return 100
      }
    }
    
    class Circle extends Shape {
      getArea() {
        return 200
      }
    }
    
    var r = new Rectangle()
    var c = new Circle()
    
    // 多态: 当对不同的数据类型执行同一个操作时, 如果表现出来的行为(形态)不一样, 那么就是多态的体现.
    function calcArea(shape: Shape) {
      console.log(shape.getArea())
    }
    
    calcArea(r)
    calcArea(c)
    
    export {}
    
    // 多态: 当对不同的数据类型执行同一个操作时, 如果表现出来的行为(形态)不一样, 那么就是多态的体现.
    function calcArea(foo) {
      console.log(foo.getArea())
    }
    
    var obj1 = {
      name: "why",
      getArea: function() {
        return 1000
      }
    }
    
    class Person {
      getArea() {
        return 100
      }
    }
    
    var p = new Person()
    
    calcArea(obj1)
    calcArea(p)
    
    
    // 也是多态的体现
    function sum(m, n) {
      return m + n
    }
    
    sum(20, 30)
    sum("abc", "cba")
    
    

    相关文章

      网友评论

          本文标题:es6中的类(五)

          本文链接:https://www.haomeiwen.com/subject/vnvrortx.html