Class和继承
Class 类
  简介
    类的由来
      JavaScript 语言中，生成实例对象的传统方法是通过构造函数
      ES6 提供了更接近传统语言的写法，引入了 Class（类）这个概念，作为对象的模板
    通过class关键字，可以定义类
    基本上，ES6 的class可以看作只是一个语法糖，它的绝大部分功能，ES5 都可以做到，新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已
  constructor 方法
    constructor()方法是类的默认方法，通过new命令生成对象实例时，自动调用该方法
    一个类必须有constructor()方法，如果没有显式定义，一个空的constructor()方法会被默认添加
  类的实例
    生成类的实例的写法，与 ES5 完全一样，也是使用new命令
    与 ES5 一样，类的所有实例共享一个原型对象
  取值函数（getter）和存值函数（setter）
    与 ES5 一样，在“类”的内部可以使用get和set关键字，对某个属性设置存值函数和取值函数，拦截该属性的存取行为
  存值函数和取值函数是设置在属性的 Descriptor 对象上的
  属性表达式
    类的属性名，可以采用表达式
  Class 表达式
    与函数一样，类也可以使用表达式的形式定义
  注意点
    类和模块的内部，默认就是严格模式
    类不存在变量提升
    函数的许多特性都被Class继承，包括name属性
    如果类的某个成员方法之前加上星号（*），就表示该方法是一个 Generator 函数
    类的方法内部如果含有this，它默认指向类的实例
  静态方法
    如果在一个方法前，加上static关键字，就表示该方法不会被实例继承，而是直接通过类来调用，这就称为“静态方法”
  实例属性的新写法
    实例属性除了定义在constructor()方法里面的this上面，也可以定义在类的最顶层
    好处是，所有实例对象自身的属性都定义在类的头部，看上去比较整齐，一眼就能看出这个类有哪些实例属性
  静态属性
    静态属性指的是 Class 本身的属性
      class Foo {
}
//仅有这种写法
Foo.prop = 1;
Foo.prop // 1
    现在有一个提案提供了类的静态属性，写法是在实例属性的前面，加上static关键字
  私有方法和私有属性
    私有方法和私有属性，是只能在类的内部访问的方法和属性，外部不能访问。这是常见需求，有利于代码的封装，但 ES6 不提供，只能通过变通方法模拟实现
      一种做法是在命名上加以区别
      另一种方法就是索性将私有方法移出类，因为类内部的所有方法都是对外可见的
      还有一种方法是利用Symbol值的唯一性，将私有方法的名字命名为一个Symbol值。但是也不是绝对不行，Reflect.ownKeys()依然可以拿到它们
    私有属性的提案
      目前，有一个提案，为class加了私有属性。方法是在属性名之前，使用#表示
  in 运算符
    V8 引擎改进了in运算符，使它也可以用来判断私有属性
  new.target 属性
    new是从构造函数生成实例对象的命令。ES6 为new命令引入了一个new.target属性，该属性一般用在构造函数之中，返回new命令作用于的那个构造函数
    注意，在函数外部，使用new.target会报错
  class Point {
}
// 等同于
class Point {
constructor() {}
}
  class A {
use(obj) {
if (#foo in obj) {
// 私有属性 #foo 存在
} else {
// 私有属性 #foo 不存在
}
}
}
  const MyClass = class Me {
getClassName() {
return Me.name;
}
};
  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 IncreasingCounter {
_count = 0;
get value() {
console.log('Getting the current value!');
return this._count;
}
increment() {
this._count++;
}
}