一、class的定义与基本用法

1.class的定义

ECMAScript 2015 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。类语法不会为JavaScript引入新的面向对象的继承模型。

2.定义类
用class定义类有两种方法:类表达式和类声明

1.类声明

class Person{  constructor(x,y){     this.x=x;     this.y=y;  }  tostring(){      return this.x+this.y} }

2.类表达式

 // 匿名类    var Person=class {        constructor(x,y){           this.x=x;           this.y=y;        }        tostring(){           return this.x+this.y        }    }    // 命名类    var Person = class Person {        constructor(x, y) {            this.x = x;            this.y = y;        }        tostring() {            return this.x + this.y        }    }

以上需要说明的点:
1.类声明/类表达式不会向函数声明/函数表达式一样提升。你要访问一个类,就必须先声明。
2.ES6类的constructor函数相当于ES5的构造函数。
3.类中定义方法时,前面不用加function,后面不得加 ,。

二、继承
extends 关键字在类声明或类表达式中用于创建一个类作为另一个类的一个子类。

//父类class Animal{    constructor(name,age){        this.name=name;        this.age=age;    }    tostring() {        return (this.name + "的年龄是:" + this.age)    }}//子类class Dogs extends Animal {    constructor(name,age,code) {        super(name, age); //  调用父类的 constructor(name,age)          this.code = code;    }    toString() {        return this.color + ' 的' + super.toString(); //  调用父类的 toString()      }      }

也可以扩展传统的基于函数的“类”(构造函数)

function Animal (name) {  this.name = name;  }Animal.prototype.speak = function () {  console.log(this.name + ' makes a noise.');}class Dog extends Animal {  speak() {    super.speak();    console.log(this.name + ' barks.');  }}var d = new Dog('Mitzie');d.speak();//Mitzie makes a noise.  Mitzie barks.

请注意,类不能继承常规(非可构造)对象。如果要继承常规对象,可以改用

var Animal = {  speak() {    console.log(this.name + ' makes a noise.');  }};class Dog {  constructor(name) {    this.name = name;  }}Object.setPrototypeOf(Dog.prototype, Animal);// If you do not do this you will get a TypeError when you invoke speakvar d = new Dog('Mitzie');d.speak(); // Mitzie makes a noise.

以上需要说明的点:
1.类必须使用new调用,否则会报错。
2.子类必须在constructor方法中调用super方法, 否则新建实例时会报错。 这是因为子类没有自己的this对象, 而是继承父类的this对象, 然后对其进行加工。 如果不调用super方法, 子类就得不到this对象。

三、constructor方法

constructor 是一种用于创建和初始化class创建的对象的特殊方法。如果不指定一个构造函数(constructor)方法, 则使用一个默认的构造函数(constructor)。

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

以上需要说明的点:
1.constructor方法默认返回实例对象(即this)。
2.在一个类中只能有一个名为 “constructor” 的特殊方法。 一个类中出现多次构造函数 (constructor)方法将会抛出一个 SyntaxError 错误。

四、super关键字

1.super作为函数时,指向父类的构造函数。super()只能用在子类的构造函数之中,用在其他地方就会报错。

class Animal{   constructor(){      console.log(new.target.name);   } } class Dogs extends Animal {   constructor() {      super();   } } new Animal() // Animalnew Dogs() // Dogs
  1. super作为对象时,指向父类的原型对象。
class A {  p() {    return 2;  }} class B extends A {  constructor() {    super();    console.log(super.p()); // 2  }}

super指向父类的原型对象,此时super.p()就相当于A.prototype.p()。
以上需要说明的点:
1.由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

五.类的prototype属性和__proto__属性

Class 作为构造函数的语法糖, 同时有prototype 属性和__proto__属性, 因此同时存在两条继承链。
1.子类与父类
1.子类的__proto__属性, 表示构造函数的继承, 总是指向父类。
2.子类prototype属性的__proto__属性, 表示方法的继承, 总是指向父类的prototype属性。

class A {}  class B extends A {}  B.__proto__ === A // true  B.prototype.__proto__ === A.prototype // true

2.实例的 proto 属性

子类实例的 proto 属性的 proto 属性, 指向父类实例的 proto 属性。 也就是说, 子类的原型的原型, 是父类的原型。

class A{}  class B extends A{}  let a = new A();  let b = new B();  console.log(b.__proto__ === a.__proto__);//false  console.log(b.__proto__.__proto__ === a.__proto__);//true