ES6——class类
在其他的众多编程语言中(例如Python),都有class(类)这个概念,而JS在ES6规范中终于补上了
定义
类是具有一些相同特征的对象,例如车都有颜色、轮子、座椅等元素,还有行驶时速,只不过不同的车,这些特征的值是不一样的
实际上class的本质,一方面是面向对象的思想,另一方面则是封装
声明
声明class时,我们直接用class关键字+类名,在其中添加构造函数constructor来给后续实例化的对象添加属性/方法,这里的this就指向实例化被生成的对象
这里的构造函数必须命名成constructor,用来接收实例化时传入的参数(也就是new 类名后的参数),但是具体如何处理还得看构造函数内部的书写
类比于对象中的方法,也可以给类添加方法,例如图例中的speedUp,相比于constructor是独立存在的
其实某种程度上说,class有点像工厂模式声明对象
方法
静态方法&静态属性
静态方法/属性是在类里声明的,只属于类自己的,不可被类实例拥有,只是类自己拥有
静态方法声明时用static关键字,写在类的内部,而静态属性则用类名.属性名=属性值的方法声明,可以写在类的内部/外部
此外,类里的方法和静态方法如果同名,不会引起冲突
静态属性的应用
获取类实例的数量
可以用静态属性来检测这个类的实例的数量,原理就是每次创建一个新的类,都是在调用类里的constructor方法,里面的代码都会被执行
这里由于Car.num这个属性是一个全局变量,因此不会被回收,但注意要在声明对象前挂上静态属性,否则无法修改静态属性
把和类相关的内容挂到静态属性上
相比于直接在类上添加属性(动态,依靠外界传入),可以在类上绑定一个静态属性,这个属性的属性值可以通过访问类来找到
好处在于:让属性和类关联,避免污染全局
静态方法的应用
提供一个公共的类相关的方法
这里主要是提供一个类的方法,不用实例化生成对象就可直接调用的方法
类表达式
可以模仿函数表达式,把一个类赋值给一个常量/变量(主要看声明)
注意声明时,类名可以在类中访问,但不可在类外面访问(这一点也类似于函数的表达式声明)
类表达式还可以自执行(类似于函数的特性),但实际开发中基本不用
getter/setter
类似于在属性中提供一个钩子,可以在获取/设置属性值时候做一些额外的事情,这些事情在设置/访问之前执行
实际上在ES5中,get/set方法就有了,可以添加在对象中,用get/set声明+属性名+(){}的方法声明(也可以理解成声明一个与属性名同名的函数),表示在访问/修改属性的时候会执行的操作
注意set中必须传入一个参数,即为设置的属性值,否则报错
如果执行的操作有和获取/修改属性相关的,则可能引发栈内存溢出
也可以用Object的defineProperty方法来设置,直接在第三个参数里写上get和set的两个函数,相当于给对象添加两个方法
不同于方法中的set,这里set函数中不一定要加形参
需要注意以下问题:
1.用defineProperty方法添加的属性不可用for-in语句遍历到的,需要给其添加enumerable属性(true),但是该属性一旦设置不可修改,否则报错
(补充案例)
2.如果一个属性有get和set方法,必须用defineProperty方法设置其为writable,否则属性是无法被修改的
(案例)
此外,访问/设置属性时,先调用get/set方法,再调用输出(console.log)等方法
(补充个案例说明问题)
(关于set和get实在是太多地方不理解……)
属性
name
用来获取类的名称
如果是类表达式声明,有类名称则返回类名称,否则返回赋值的变量名称
new.target
返回的是new声明后的类/函数
该属性不可直接调用,需要放在类/函数里
继承
ES6的类也可以继承,其中被继承的类叫父类(基类),继承的类为子类
类似于对象的继承,类的继承也可以让子类获取父类的方法和属性,从而实现子类属性/方法的添加
extends
ES6的类中,可使用extends来继承父类的属性,并在constructor里给子类的属性赋值前,使用super方法来调用父类的构造函数,以实现继承
super
上面的例子中可以看出,super可以在子类的构造函数中使用,以调用父类构造函数
此外还可以作为对象的方式调用,但是在静态方法/非静态方法里使用时,访问到的分别是父类的原型/对象
此外,在调用super时,父类的this始终是子类的this