zoukankan      html  css  js  c++  java
  • 【JS核心概念】Class的基本语法

    一、简单使用

        // 定义一个Animal类
        class Animal {
            // 构造方法,相当于ES5中的构造函数
            // this代表的是实例对象
            constructor(kind) {
                this.kind = kind;
            }
            getKind() {
                console.log(this.kind);
            }
        }
    
    • 类必须使用new运算符调用,直接调用会报错
        // 类必须使用new运算符来调用,如果直接调用会报错,这点跟ES5的构造函数不一样
        const cat = new Animal('cat');
        // const cat = Animal('cat'); // TypeError: Class constructor Animal cannot be invoked without 'new'
        cat.getKind(); // cat
    
    • 类的数据类型是函数,类本身就指向构造函数
        console.log(typeof Animal); // function
        console.log(Animal === Animal.prototype.constructor); // true
    
    • 类中的所有方法都是定义在类的prototype属性上的
    • 实例的属性除非显式的定义在其本身(即this对象上),否则都是定义在原型上
        // kind为实例属性
        console.log(Object.getOwnPropertyNames(cat)); // [ 'kind' ]
        // constructor、getKind为原型上的方法
        console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(cat))); // [ 'constructor', 'getKind' ]
    
    • 类不存在变量提升,因此在继承的时候父类必须在子类之前定义
        const foo = new Foo(); // ReferenceError: Foo is not defined
        class Foo {}
    

    二、constructor

    • constructor是类的默认方法,它相当于ES5中的构造函数,当我们使用new命令生成对象实例时,会自动调用该方法。
    • 一个类必须有constructor方法,如果没有显示定义,会默认添加一个空的constructor方法。
        class Animal {
        
        }
        // 等同于
        calss Animal {
            constructor() {}
        }
    
    • constructor方法默认返回实例对象,不过也可以指定返回另一个对象。
        class Foo {
            constructor() {
                // 返回一个数组
                return new Array()
            }
            print() {
                console.log('124')
            }
        }
        
        // 实例对象不再是Foo类的实例,而是Array的实例
        const foo = new Foo();
        console.log(foo instanceof Foo); // false
        console.log(foo instanceof Array); // true
        // 无法调用Foo类中的方法
        foo.print(); // TypeError: foo.print is not a function
    

    三、this的指向

    类的方法中如果含有this,则默认指向类的实例。但是如果单独使用该方法,可能会报错。

        class Foo {
            printName() {
                this.print('hahah');
            }
            print(text) {
                console.log(text);
            }
        }
        
        const foo = new Foo();
        // 将printName单独提出来
        const printName = foo.printName;
        // 此时printName中的this指向运行时所在的环境(这里是Window),找不到print方法
        printName(); // TypeError: Cannot read property 'print' of undefined
    

    解决方法:

    • 在类的构造方法constructor中绑定this,当new一个实例的时候,会执行该方法
        class Foo {
            constructor() {
                // bind方法会创建一个新的绑定函数,绑定函数的执行上下文为this
                this.printName = this.printName.bind(this)
            }
            printName() {
                this.print('hahah');
            }
            print(text) {
                console.log(text);
            }
        }
        
        const foo = new Foo();
        const printName = foo.printName;
        printName(); // hahah
    
    • 使用箭头函数
        class Foo {
            constructor() {
                // 在实例对象上新增了一个方法printName
                this.printName = () => {
                    this.print('lalal')
                }
            }
            printName() {
                this.print('hahah');
            }
            print(text) {
                console.log(text);
            }
        }
        
        const foo = new Foo();
        const printName = foo.printName;
        // 调用的是实例的printName,而不是原型上的printName
        printName(); // lalal
    

    四、静态方法和静态属性

    4.1 静态方法
    • 定义:静态方法指的是Class本身的方法,而不是prototype属性上的方法;

    • 语法: 在类的方法前加上static关键字;

    • 特点:

      • 类相当于实例的原型,默认情况下类中的所有方法都会被实例继承,但是静态方法不会被实例继承,而是通过类直接调用
          class Foo {
              // 静态方法
              static sayHi() {
                  console.log('Hi')
              }
          }
          
          const foo = new Foo();
          // 实例调用静态方法会报错
          // foo.sayHi(); // TypeError: foo.sayHi is not a function
          Foo.sayHi(); // Hi
      
      • 父类的静态方法可以被子类的继承
          class Bar extends Foo {}
          Bar.sayHi(); // Hi
      
      • 静态方法可以通过super调用,因为当super作为对象使用时,在静态方法中指向父类
          class Bar extends Foo {
              static sayHello() {
                  super.sayHi()
              }
          }
          Bar.sayHello(); // Hi
      
    4.2 静态属性
    • 定义:静态属性值类本身的属性,而不是定义在实例对象上(this)的属性

    • 语法:

      • 目前只能使用Class.propname的写法,因为ES6规定,Class内部只有静态方法,没有静态属性
      // 添加静态属性prop
      Foo.prop = 1;
      
      const foo = new Foo();
      // 通过类访问
      console.log(Foo.prop); // 1
      // 不能通过实例访问
      console.log(foo.prop); // undefined
      
      • 提案:目前有一个提案,规定可以在Class内部使用static关键字+等式的方法为类添加静态属性
          class Foo {
              // 静态属性
              static prop = 1;
              // 提案也规定了Class的实例属性可以用等式写入类的定义之中
              name = 'Lily';
              constructor(){
                  console.log(Foo.prop, this.name); // 1 Lily
              }
          }
      

    五、new.target属性

    ES6为new运算符添加了new.target属性,(在构造函数中)返回new命令所左右的构造函数。如果构造函数不是通过new命令调用的,那么new.target会返回undefined,因此可以使用该属性确定构造函数是如何调用的。

        function Person(name) {
            if (new.target === Person) {
                this.name = name;
            } else {
                throw new Error('必须使用new生成实例')
            }
        }
        const person1 = new Person('Lily');
        const person2 = Person('Lily'); // Error: 必须使用new生成实例
    
        class Foo {
            constructor() {
                console.log(new.target === Foo);
            }
        }
        new Foo(); // true
    



  • 相关阅读:
    串口通信(2)
    串口通信(1)
    extern关键字的使用
    volatile关键字的使用
    Uart串口与RS232串口的区别
    DSP5509的时钟发生器(翻译总结自TI官方文档)
    DSP中的cmd文件
    pragma伪指令
    在C语言中嵌入汇编语言
    another app is currently holding the yum lock;waiting for it to exit...
  • 原文地址:https://www.cnblogs.com/jiafifteen/p/12201334.html
Copyright © 2011-2022 走看看