在es6 之后,之前被预留关键字的class被正式使用,在es中class与面向对象的程序设计语言(java)中的类存在一定的区别(如:函数重载等、受保护成员protected),在es6中class并没有引入一种新的面向对象的继承机制,而是js 原型继承的一种语法糖。简单理解:js中class其实就是一个特殊的function,因此同样它也具有我们上文中的function特性,上文中已经说明了很多关于function的特性,下文重点介绍关于class。
1、class 与 function区别
1.1、class与function声明,如var与let、const 相似,先声明后使用,不能重复定义,存在变量提升,但是无法初始化(注:根据es6中介绍class、let、const不存在变量提升,这里大家也可以根据文档理解,不通过声明流程,有兴趣的同学可以自己尝试看一下错误信息,在理解记忆过程中切忌记住一种思路就行,别弄混淆),class调用必须通过new 关键字。
2.2、在es中class不同于java中class,它不存在私有方法与私有属性,因此es中class的属性和方法都是公开的(typescript提供了私有属性,同步面向对象类的实现)。在es中function可通过闭包、散列表等方式实现,虽然class没有直接提供私有方法和属性,但是我们可以通过一些变通法实现私有化,如:typescript、外部私有、Symbol。如下图:
2.3、class中的static 属性:用于定义类中的静态方法和静态属性关键字,该方式声明的方法与属性,只能通过类名调用,可被继承,并且定义的方法的this指向类而不是实例。
上图可看出,当类中的方法单独使用时,this指向全局对象,因此我们要解决这种问题,可通过改变this指向解决:如constructor中bind 变更this、箭头函数、代理对象等,可参靠es6文档,这里不做详细介绍。
2、class关键字
在class中所有方法和属性都是定义在class的原型上面,使用时也是调用其原型上的方法(注:类中定义的方法都是不可枚举的),在类中必须有一个constructor方法。下面我们通过babel来简单看一下class的实现:
由上图可看出类实现就是在其构造函数或其原型设定用户属性。在构造过程中必须使用new关键字。
2.1 class 继承问题
在es中有多种继承方式,具体下一篇作详细介绍,在class 中extend 关键字实现继承,结构比传统函数的原型继承清晰方便。es6中的继承流程为:创建父类的实例对象this,再通过子类的构造函数修改this。在class的继承中,子类的_proto_属性表示构造函数的继承,指向父类,子类prototype属性的_proto_属性,表示方法的继承,总是指向父类的prototype属性。
因此在理解了class类的实现原理后,有兴趣的同学可以尝试通过es5实现es6的extends 关键字。关于js的继承问题,下文做介绍。
3、总结
class 关键字的引入,使得编程更趋向与面向对象的编程,让对象原型的写法更加清晰化,阅读性、维护性都得到了相应的提高。大家在学习时,更多的应该关注关于一些es6新特性的实现,在开发中,希望每位同学都能把十万个为什么运用到淋漓尽致。端午将近,提前祝大家端午节快乐,下一篇,暂时跳出es圈,介绍一下关于服务端的一些看法与认识。
下一篇:服务端渲染(SSR)