class介绍

   ES6引入了Class(类)这个概念,做为对象的模板。经过class关键字,能够定义类。基本上,ES6的class能够看做只是一个语法糖,它的绝大部分功能,ES5均可以作到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。编程

ES6的类,彻底能够看做构造函数的另外一种写法。浏览器

类的数据类型就是函数,类自己就指向构造函数。app

使用的时候,也是直接对类使用new命令,跟构造函数的用法彻底一致。函数

constructor方法

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

类的构造函数,不使用new是无法调用的,会报错。这是它跟普通构造函数的一个主要区别,后者不用new也能够执行。this

生成类的实例对象的写法,与ES5彻底同样,也是使用new命令。若是忘记加上new,像函数那样调用Class,将会报错。spa

与ES5同样,实例的属性除非显式定义在其自己(即定义在this对象上),否则都是定义在原型上(即定义在class上)prototype

 

xy都是实例对象point自身的属性(由于定义在this变量上),因此hasOwnProperty方法返回true,而toString是原型对象的属性(由于定义在Point类上),因此hasOwnProperty方法返回false。这些都与ES5的行为保持一致。3d

不存在变量提高

Class不存在变量提高(hoist),这一点与ES5彻底不一样。code

上面代码中,Foo类使用在前,定义在后,这样会报错,由于ES6不会把类的声明提高到代码头部。这种规定的缘由与下文要提到的继承有关,必须保证子类在父类以后定义。对象

Class的继承

 Class之间能够经过extends关键字实现继承,这比ES5的经过修改原型链实现继承,要清晰和方便不少。

 

上面代码定义了一个ColorPoint类,该类经过extends关键字,继承了Point类的全部属性和方法。可是因为没有部署任何代码,因此这两个类彻底同样,等于复制了一个Point

 

constructor方法和toString方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。

子类必须在constructor方法中调用super方法,不然新建实例时会报错。这是由于子类没有本身的this对象,而是继承父类的this对象,而后对其进行加工。若是不调用super方法,子类就得不到this对象。

ES5的继承,实质是先创造子类的实例对象this,而后再将父类的方法添加到this上面(Parent.apply(this))。ES6的继承机制彻底不一样,实质是先创造父类的实例对象this(因此必须先调用super方法),而后再用子类的构造函数修改this

另外一个须要注意的地方是,在子类的构造函数中,只有调用super以后,才可使用this关键字,不然会报错。这是由于子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例

类的prototype属性和__proto__属性 

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

(1)子类的__proto__属性,表示构造函数的继承,老是指向父类。

(2)子类prototype属性的__proto__属性,表示方法的继承,老是指向父类的prototype属性。

 

上面代码中,子类B__proto__属性指向父类A,子类Bprototype属性的__proto__属性指向父类Aprototype属性。

 这样的结果是由于,类的继承是按照下面的模式实现的。

 

Object.setPrototypeOf方法的实现:

 

故上面代码等同于这里的代码

这两条继承链,能够这样理解:

做为一个对象,子类(B)的原型(__proto__属性)是父类(A);做为一个构造函数,子类(B)的原型(prototype属性)是父类的实例。

相关文章
相关标签/搜索