zoukankan      html  css  js  c++  java
  • ES6 Class(类)的继承与常用方法

    一、ES6 类的定义

    ES5 构造函数的写法:

    function Point(x, y) {
        this.x = x;
        this.y = y;
    }

    ES6 引入了 Class(类),通过class关键字,可以定义类。

    class Point {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
    }

    这里,ES6 的 Point 类的构造方法对应前面 ES5 的构造函数 Point,代码中的 constructor 是构造方法。

    关于 constructor

    constructor 是类的默认方法,通过 new 命令生成对象实例时,自动调用该方法。

    一个类必须有 constructor 方法,如果没有显式定义,一个空的 constructor 方法会被默认添加:

    class Point {
    }
    
    // 等同于
    class Point {
        constructor() {}
    }

    二、ES6 类的实例

    生成类的实例与 ES5 一样,也是用 new 命令。

    但构造函数的实例不用 new 也可以执行,而类必须用 new,否则会报错:

    class Point {
      // ...
    }
    
    // 报错
    var point = Point(2, 3);
    
    // 正确
    var point = new Point(2, 3);

    三、ES6 类的继承

    1、Object.getPrototypeOf()

    Object.getPrototypeOf 方法可以用来从子类上获取父类,判断一个类是否继承了另一个类

    Object.getPrototypeOf(foo) === Foo
    // true

     2、extends 关键字实现继承

    class Parent{
      constructor(lastName='Liu'){
        this.lastName=lastName;
      }
    }
    class Child extends Parent{
      constructor(lastName){
        super(lastName);
      }
    }
    console.log(new Child('Chen'));
    
    // 输出结果

    3、super 关键字

    ① super 作为函数调用时,代表父类的构造函数(ES6 要求,子类的构造函数必须执行一次 super 函数,否则会报错)

    class A {}
    
    class B extends A {
      constructor() {
        super();
      }
    }

    注意,super 虽然代表了父类 A 的构造函数,但返回的是子类 B 的实例,即 super 内部的 this 指的是 B 的实例,因此 super() 在这里相当于 A.prototype.constructor.call(this)

    class A {
      constructor() {
        console.log(new.target.name);
      }
    }
    class B extends A {
      constructor() {
        super();
      }
    }
    new A() // A
    new B() // B

    上面代码中,new.target 指向当前正在执行的函数。可以看到,在 super() 执行时,它指向的是子类 B 的构造函数,而不是父类 A 的构造函数。也就是说,super() 内部 的 this 指向的是子类 B

    ②super 作为对象时,在普通方法中指向父类的原型对象;在静态方法中则指向父类

    class A {
      p() {
        return 2;
      }
    }
    
    class B extends A {
      constructor() {
        super();
        console.log(super.p()); // 2
      }
    }
    
    let b = new B();

    上面代码中,子类 B 当中的 super.p(),就是将 super 当作一个对象使用。这时,super 在普通方法之中,指向 A.prototype,所以 super.p() 就相当于 A.prototype.p()

    注意,使用 super 的时必须显式指定是作为函数、还是作为对象使用,否则会报错

    class A {}
    
    class B extends A {
      constructor() {
        super();
        console.log(super); // 报错
      }
    }

    上面代码中,console.log(super) 当中的 super,无法看出是作为函数使用,还是作为对象使用,所以 JavaScript 引擎解析代码的时候就会报错

    super 关键字扩展

    ① 类的继承

    ② 类的重写(覆盖)

    类重写后使用 super 关键字重新调用父类方法

    四、getter 和 setter

    与 ES5 一样,在“类”的内部可以使用 get 和 set 关键字,对某个属性设置取值函数和存值函数,拦截该属性的存取行为

    1、getter(取值函数)

    class Parent{
      constructor(name='Winnie'){
        this.name=name;
      }
      get longName(){
        return 'Liu'+this.name;
      }
    }
    let getterName=new Parent();
    console.log(getterName.longName);  // LiuWinnie

    2、setter(存值函数)

    class Parent{
      constructor(name='Winnie'){
        this.name=name;
      }
      get longName(){
        return 'Liu'+this.name;
      }
      set longName(value){
        this.name=value;
      }
    }
    let setterName=new Parent();
    setterName.longName='Honey';
    console.log(setterName.longName);    // LiuHoney

    五、public、private 和 protected

    1、public

    允许在类的内外被调用

    2、private

    只允许在类的内部被调用

    3、protected

    允许在类的内部及继承的子类中调用

    六、静态方法/属性

    类相当于实例的原型,所有在类中定义的方法,都会被实例继承。

    但如果在一个方法前加上 static 关键字,则该方法不会被实例继承,而是直接通过类来调用,这种方法称为静态方法。

    1、静态方法:使用 static 关键字

    class Parent{
      static tell(){
        console.log('hello');
      }
      tell(){
        console.log('world');
      }
    }
    Parent.tell();    // hello

    以上代码还可以看出静态方法可以与非静态方法重名

    2、静态属性:直接用 .属性名

    class Parent {
    }
    
    Parent.lastName = 'Liu';
    console.log(Parent.lastName);  // Liu

    上面代码为 Parent 类定义了一个静态属性 lastName

    七、name 属性

    由于本质上,ES6 的类只是 ES5 的构造函数的一层包装,所以函数的许多特性都被 Class 继承,包括 name 属性

    class Point {}
    Point.name // "Point"

    name 属性总是返回紧跟在 class 关键字后面的类名

    let foo = class Foo {
      constructor(){
        this.name = 'Leo'
      }
    }
    let child = new foo();
    console.log(foo.name);    // Foo

    八、new.target 属性

    new 是从构造函数生成实例对象的命令。ES6 为 new 命令引入了一个 new.target 属性,该属性一般用在构造函数之中,返回 new 命令作用于的那个构造函数。如果构造函数不是通过 new 命令或 Reflect.construct() 调用的,new.target 会返回 undefined,因此这个属性可以用来确定构造函数是怎么调用的

    function Person(name) {
      if (new.target !== undefined) {
        this.name = name;
      } else {
        throw new Error('必须使用 new 命令生成实例');
      }
    }
    
    // 另一种写法
    function Person(name) {
      if (new.target === Person) {
        this.name = name;
      } else {
        throw new Error('必须使用 new 命令生成实例');
      }
    }
    
    var person = new Person('张三'); // 正确
    var notAPerson = Person.call(person, '张三');  // 报错

    上面代码确保构造函数只能通过 new 命令调用

    需要注意的是,子类继承父类时,new.target 会返回子类

  • 相关阅读:
    WinForm获取窗体关闭原因和是否取消关闭值
    DIV CSS 居中代码(以及靠右)
    C#获取本机所有IP地址(包括局域网和本机外网IP)
    C# WinForm关闭窗体确认
    .NET WinForm全屏和退出以及蓝屏黑屏等
    HTML5标签
    C# 文件、文件夹操作语句(删除,创建,移动,检查是否存在)
    jquery聚焦文本框
    JS当前页面登录注册框,固定DIV,底层阴影
    Visual Studio 怎样添加引用
  • 原文地址:https://www.cnblogs.com/Leophen/p/11234191.html
Copyright © 2011-2022 走看看