• ES6学习之Class


    一、定义类(ES6的类,完全可以看做是构造函数的另一种写法)

    class Greet {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        sayHello() {
            console.log(this.x + " " + this.y)
        }
    }
    let a = new Greet("hello", "everybody");
    a.sayHello() //hello everybody

    《注》:

    • 以上定义的类如果用ES5的构造函数实现如下:
    function Greet(x, y) {
        this.x = x;
        this.y = y;
        this.sayHello = function () {
            console.log(this.x + " " + this.y)
        }
    }
    
    let a = new Greet("hello", "everybody");
    a.sayHello() //hello everybody
    • 类的数据类型就是函数,类本身就指向构造函数
    typeof Greet; //function
    Greet === Greet.prototype.constructor //true
    • 类的所有方法都定义在类的prototype属性上面
    class Greet {
        constructor() {...}
        sayHello() {...}
        sayHi(){...}
    }
    等同于
    Greet
    Greet.prototype = {
      constructor() {},
      sayHello() {},
      sayHi() {},
    };
    constructor方法
    • 是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
    class Greet {
    }
    // 等同于
    class Greet {
      constructor() {}
    }
    • constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象。
    class Foo {
      constructor() {
        return Object.create(null);
      }
    }
    
    new Foo() instanceof Foo
    // false

    类的实例对象:

    • 实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。
    class Greet {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        sayHello() {
            console.log(this.x + " " + this.y)
        }
    }
    let a = new Greet("hello", "everybody");
    // x,y都是实例对象a自身的属性,因为定义在this上
    a.hasOwnProperty('x') // true
    a.hasOwnProperty('y') // true
    //sayHello是原型对象的属性,因为定义在Greet上
    a.hasOwnProperty('sayHello') // false
    a.__proto__.hasOwnProperty('sayHello') // true
    • 类的所有实例共享一个原型对象
    let a = new Greet("hello", "everybody");
    let b = new Greet("hello", "everybody");
    
    a.__proto__ === b.__proto__  //true

    Class表达式:

    const MyClass = class Me {
      getClassName() {
        return Me.name;
      }
    };   //类的名字是MyClass而不是Me,Me只在 Class 的内部代码可用,指代当前类。
    //如果类的内部没用到的话,可以省略Me
    const MyClass = class { 
        ...
     };

    不存在变量提升:必须先定义类,再使用

    私有方法:

    • 利用Symbol值的唯一性
    const bar = Symbol('bar');
    const snaf = Symbol('snaf');
    
    export default class myClass{
    
      // 公有方法
      foo(baz) {
        this[bar](baz);
      }
    
      // 私有方法
      [bar](baz) {
        return this[snaf] = baz;
      }
    
      // ...
    };
    • 利用#标识:
    class Greet {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        #sayHello() {
            console.log(this.x + " " + this.y)
        }
    }

    Class 的取值函数(getter)和存值函数(setter):在“类”的内部可以使用getset关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。

    class MyClass {
      constructor() {
        // ...
      }
      get prop() {
        return 'getter';
      }
      set prop(value) {
        console.log('setter: '+value);
      }
    }
    
    let inst = new MyClass();
    
    inst.prop = 123;
    // setter: 123
    
    inst.prop
    // 'getter'

    Class 的静态方法:加上static关键字,表示该方法不会被实例继承,而是直接通过类来调用

    class Foo {
      static classMethod() {
        return 'hello';
      }
    }
    
    Foo.classMethod() // 'hello'
    
    var foo = new Foo();
    foo.classMethod()
    // TypeError: foo.classMethod is not a function
    • 如果静态方法包含this关键字,这个this指的是类,而不是实例
    • 父类的静态方法,可以被子类继承
    • 静态方法也是可以从super对象上调用的

    Class 的静态属性和实例属性

    • 静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性,定义方法如下:
    class MyClass {
      static myStaticProp = 42;
    
      constructor() {
        console.log(MyClass.myStaticProp); // 42
      }
    }
    • 类的实例属性可以用等式,写入类的定义之中
    class MyClass {
      myProp = 42;
    
      constructor() {
        console.log(this.myProp); // 42
      }
    }

    new.target 属性:如果构造函数不是通过new命令调用的,new.target会返回undefined

    用来确定构造函数是怎么调用的。

    function Person(name) {
      if (new.target !== undefined) {
        this.name = name;
      } else {
        throw new Error('必须使用 new 命令生成实例');
      }
    }

    二、Class继承通过extends关键字实现继承

    class Point {
    }
    
    class ColorPoint extends Point {
    }

    supper:

    • 子类必须在constructor方法中调用super方法(子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工)
    class Point { /* ... */ }
    
    class ColorPoint extends Point {
      constructor() {
      }
    }
    
    let cp = new ColorPoint(); // ReferenceError
    • 如果子类没有定义constructor方法,这个方法会被默认添加
    class ColorPoint extends Point {
    }
    
    // 等同于
    class ColorPoint extends Point {
      constructor(...args) {
        super(...args);
      }
    }
    • 在子类的构造函数中,只有调用super之后,才可以使用this关键字(子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例)
    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    }
    
    class ColorPoint extends Point {
      constructor(x, y, color) {
        this.color = color; // ReferenceError
        super(x, y);
        this.color = color; // 正确
      }
    }
    • super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。且只能用在子类的构造函数之中,用在其他地方就会报错
    class A {}
    
    class B extends A {
      constructor() {
        super();
      }
    }  //super虽然代表了父类A的构造函数,但是返回的是子类B的实例
    • super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。

              a)普通方法中:

    class A {
      p() {
        return 2;
      }
    }
    
    class B extends A {
      constructor() {
        super();
        console.log(super.p()); // 2
      }
    }  //指向父类的原型对象
    
    let b = new B();

    b) 静态方法中:

    class Parent {
      static myMethod(msg) {
        console.log('static', msg);
      }
    
      myMethod(msg) {
        console.log('instance', msg);
      }
    }
    
    class Child extends Parent {
      static myMethod(msg) {
        super.myMethod(msg);
      }
    
      myMethod(msg) {
        super.myMethod(msg);
      }
    }
    
    Child.myMethod(1); // static 1
    
    var child = new Child();
    child.myMethod(2); // instance 2
  • 相关阅读:
    计算机视觉在生物力学和运动康复中的应用和研究
    摄影测量(计算机视觉)中的三角化方法
    用于机器人导航辅助的6自由度姿态估计的平面辅助视觉惯性里程计
    一文详解固态激光雷达的里程计(loam_livox)
    聊聊这两年学习slam啃过的书
    一种用于三维物体建模的精确、鲁棒的距离图像配准算法
    汇总|实时性语义分割算法(全)
    Crypto练习之CRC32应用
    Lower-SQL至系统沦陷
    Crypto练习之替换密码
  • 原文地址:https://www.cnblogs.com/sghy/p/8005857.html
Copyright © 2020-2023  润新知