ES6 class

作者: maomizone | 来源:发表于2022-03-28 15:09 被阅读0次

ES6的class出来后,我们再也看不到那烦人的prototype了,因为我之前用的是java语言开发,看到这个class就非常熟悉,现在赶紧来学习一下它的语法,然后总结一波

1.定义类
  class Point {
    // new Point()的时候会自动执行构造方法,返回一个新的对象,this绑定到该对象
    constructor(x, y) {
      this.x = x;
      this.y = y;
    }

    // 类中定义的方法默认定义在原型对象上,且是不可枚举的
    toStr() {
      console.log(`${this.x}, ${this.y}`);
    }
  }
  • 类里面必须有constructor方法,它做了以下几件事(其实和es5一毛一样)
  1. 创建一个新对象
  2. this指向这个新对象
  3. 对象添加属性
  4. 给这个新对象设置关联对象
  5. 返回对象
  • 验证一波
  const p = new Point(666, 888)
  console.log(Object.getOwnPropertyNames(p)); // ['x', 'y']
  console.log(Object.getPrototypeOf(p) === Point.prototype); // true
  • 类中的方法不需要function,这样会报错,用fn(){}这样声明方法,另外类中的方法默认添加到类的prototype属性指向的对象上面,且是不可枚举的
  // Object.getOwnPropertyNames获得自身对象的所有属性名字,包括不可枚举的(不含关联对象的)
  // Object.keys获得自身对象的所有属性名字,不包括不可枚举的(不含关联对象的)
  console.log(Object.getOwnPropertyNames(Point.prototype)); // ['constructor', 'toStr']
  console.log(Object.keys(Point.prototype)); // []
  // for in 获得整个原型链上面的可以枚举的所有属性名
  Point.prototype.a = 1
  Point.prototype.test = function (){}
  Object.prototype.x = function (){}
  for(let k in Point.prototype){
    console.log(k); // a test x
  }
2.继承
  class ColorPoint extends Point {
    constructor(x, y, m, n) {
      super(x, y);

      // 可以通过浅拷贝的方式,再加上解构来赋值
      // this.m = m;
      // this.n = n;
      Object.assign(this, { m, n })
    }

    toStr2() {
      super.toStr();
    }

    test() {
      super.num = 666
    }
  }

这里有三点需要注意:

【注意点1】 在子类的constructor方法里面,第一行必须是super(),为什么呢?

这边我摘抄了阮一峰老师的解答

super在这里表示父类的构造函数,用来新建一个父类的实例对象
ES6 规定,子类必须在constructor()方法中调用super(),否则就会报错。
这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造后返回
如果不调用super()方法,子类就得不到自己的this对象

为什么子类的构造函数,一定要调用super()?原因就在于 ES6 的继承机制,与 ES5 完全不同。ES5 的继承机制,是先创造一个独立的子类的实例对象,然后再将父类的方法添加到这个对象上面,即“实例在前,继承在后”。ES6 的继承机制,则是先将父类的属性和方法,加到一个空的对象上面,然后再将该对象作为子类的实例,即“继承在前,实例在后”。这就是为什么 ES6 的继承必须先调用super()方法,因为这一步会生成一个继承父类的this对象,没有这一步就无法继承父类。

但我看完更加懵逼了,我觉得讲的不正确,因为继承关系,说到底就是两个对象之间建立关联,具体见我上一篇笔记,下面发表一下我的观点:

相当于Point.prototype.constructor.call(this, x, y)
然后父类构造函数执行刚刚说的5件事,然后我们子类构造函数拿着返回的对象继续加工

  class ColorPoint extends Point {
    constructor(x, y, m, n) {
      super(x, y);
      Object.assign(this, { m, n })
    }
  }

【注意点2】 如何调用父类方法?
使用super.调用父类方法,相当于Point.prototype.toStr.call(this)

 toStr2() {
      super.toStr();
 }

【注意点3】 使用super赋值
赋值操作时,这里不是Point.prototype.num = 666,而是this.num = 666,这里是一个坑,不方便理解,只能死记硬背

test() {
      super.num = 666
}

下面验证一波

  const color = new ColorPoint(1, 2, 3, 4)
  console.log(Object.getOwnPropertyNames(color)); // x y m n
  console.log(Object.getOwnPropertyNames(ColorPoint.prototype)); // ['constructor', 'toStr2']
  console.log(Object.getPrototypeOf(color) === ColorPoint.prototype); // true
  console.log(Object.getPrototypeOf(ColorPoint.prototype) === Point.prototype); // true

  color.toStr2() // 1, 2

  color.test()
  console.log(Object.getOwnPropertyNames(color)); // x y m n num
  console.log(color.num); // 666

相关文章

网友评论

      本文标题:ES6 class

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