【ECMAScript 学习笔记】5.关于 Class

Class基本语法

  ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类:

    // 定义 Point 类
    class Point {
        // 定义 Ponit 类的构造函数
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }

        // 定义方法
        toString() {
            console.log(`x:${this.x}, y:${this.y}`);
        }
    }

  ES6 的类,完全可以看作构造函数的另一种写法:

    class Point { 
        constructor() {

        }
    };

    console.log(typeof Point); // "function"

    console.log(Point === Point.prototype.constructor); // true

事实上,类的所有方法都定义在类的 prototype 属性上。在类的实例上调用方法,其实就是调用原型的方法。*

  Object.assign 方法可以向类添加多个方法:

    Object.assign(Point.prototype,{
        toValue() {},
        toString() {}
    })

ES6 中类的内部所有定义的方法,都是不可枚举的,这一点与 ES5 的行为不一致。

    class Point {
        constructor(){}
        toString(){}
    }

    console.log(Object.keys(Point.prototype)); // []

若想要获取其内部定义的所有方法,则可通过 Object.getOwnPropertyNames 方法获取

    console.log(Object.getOwnPropertyNames(Point.prototype));

  可使用表达式定义类的属性名

    let methodName = "getArea";

    class Square {
        constructor(){}

        [methodName](){}
    }

constructor 方法

  constructor 方法是类的默认方法,通过 new 命令生成对象实例。自动调用该方法。一个对象必须有 constructor 方法,如果没有显示定义,一个空的 constructor 方法会被默认添加。

  constructor 方法默认返回实例对象(即 this),完全可以指定返回另一个对象。

    class Foo {
        constructor() {
            return Object.create(null);
        }
    }

Class 表达式

  与函数一样, Class 也可以使用表达式的形式定义。

    const MyClass = class Me {
        getClassName() {
            return Me.name;
        }
    }

Class 的继承

  Class 之间可以通过 extends 关键字实现继承,这比 ES5 通过修改原型链实现继承,要清晰和方便很多:

    class ColorPoint extends Point {

        constructor(x,y) {
            super(x,y); // 用于表示 父类的构造函数,用来新建父类的 this 对象。
        }
    }

子类必须在 constructor 方法中调用 super 方法,否则新建实例会报错。这是因为子类没有自己的 this 对象,而是继承父类的 this 对象,然后对其进行加工。

ES5 的继承,实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this上(Parent.applu(this))。ES6 的继承机制完全不同,实质是先创造父类的实例对象 this(所以必须先调用 super 方法),然后再用子类的构造函数修改 this

类的 prototype 属性和 proto 属性

  大多数浏览器的 ES5 实现之中,每一个对象都有 __proto__ 属性,指向对应的构造函数的 prototype 属性。
Class 作为构造函数的语法糖,同时有 prototype__proto__ 属性,因此同时存在两条继承链:

  1. 子类的 __proto__ 属性,表示构造函数的继承,总是指向父类
  2. 子类 prototype 属性的 __proto__ 属性,表示方法的继承,总是指向父类的 prototype 属性。

Object.getPrototypeOf

  Object.getPrototypeOf 方法可以从子类上获取父类

    Object.getPrototypeOf(ColorPoint); // Ponit

super 关键字

  1. 作为函数调用时,super 代表父类的构造函数。
  2. 作为调用时,super 代表父类,可以直接引用父类实例的属性和方法,也可以引用父类的静态方法。

实例的 proto 属性

   子类实例的 __proto__ 属性的 __proto__ 属性,指向父类实例的 __proto 属性。

Class 的取值函数(getter)和存值函数(setter)

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

    class MyClass {
        constructor() {
            this.element = '';
        }

        get prop() {
            return this.element;
        }

        set prop(value) {
            this.element = value;
        }
    }

Class 的静态方法

  在方法前加上 static 关键字,就表示该方法不会被实例继承,而是直接通过类来调用。

    class MyClass {
        constructor() {
            this.element = '';
        }
        static classMethod() {
            return false;
        }
    }

    MyClass.classMethod();

new.target 属性

  new.target 属性用于确定构造函数是怎么调用的。在构造函数中返回 new 命令作用于的那个对象函数,如果不是通过 new 命令调用的,则返回 undefined

猜你喜欢

转载自blog.csdn.net/hvkcoder/article/details/80014095
今日推荐