类的声明
类是什么
类作为对象的模板,只是一个语法糖
class 关键字是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
// ES5创建构造函数
function Hero() {
this.name = "张无忌"
this.sayMe = function () {
console.log("this is 张无忌");
}
}
Hero.prototype={
age:18,
myjob:function () {
console.log('i am 教主');
}
}
var hero = new Hero()
//ES6创建类
class Hero{
//构造器
constructor() {
this.name = "张无忌"
this.sayMe = function () {
console.log("this is 张无忌");
}
}
}
类的声明
- 类的声明方式
class className{内部结构}
- class关键字 - 用于创建类
- className - 表示创建的类名
class Hero{}// Identifier 'Hero' has already been declared
class Hero{}
类声明不允许再次声明已经存在的类,否则将会抛出一个类型错误。
- 类的表达方式
const/let/var myClass = class[className]{内部结构}
- class关键字 - 用于创建类
- myClass/className - 表示创建的类名
- myClass - 类名,用于后面的代码逻辑进行调用
- className - 类名,用于当前类的内部使用的
let Hero = class hero{// Identifier 'Hero' has already been declared
}
const Hero = class hero{// Identifier 'Hero' has already been declared
}
var Hero = class hero{// 不报错
}
和函数表达式相同的一点是,类表达式可以是命名也可以是匿名的。如果是命名类表达式,这个名字只能在类体内部才能访问到。
构造函数
用于创建和初始化类中创建的一个对象的一种特殊方法。
-
在一个类中只能有一个名为“constructor”的特殊方法。一个类中出现多次构造函数(Constructor)方法将会抛出一个 SyntaxErcOr错误。
-
在一个构造方法中可以使用super 关键字来调用一个父类的构造方法。
-
如果没有显式指定构造方法,则会添加默认的constructor方法。
-
如果不指定一个构造函数( constructor )方法,则使用一个默认的构造函数( constructor )
class Hero {
//构造器
constructor() {
this.name = '张无忌'
this.sayMe = ()=>{
console.log('this is zhangwuji');// this is zhangwuji
}
}
}
let hero = new Hero()
console.log(hero);// Hero { name: '张无忌' }
hero.sayMe()
getter与setter
与ES5一样,在“类”的内部可以使用get
和 set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为
- ES5
get
和set
关键字在ES5是自己
定义的- ES6
get
和set
关键字在ES6是内部
定义的
//ES6
class Hero {
constructor() {
this.v = 100
}
get getV(){
return this.v
}
set serV(value){
this.v = value
}
}
var obj = new Hero()
obj.v(1000)
console.log(obj.v);// 1000
不允许重复声明
- 声明类时,是不存在
声明提前
的现象的
new obj()//ReferenceError: obj is not defined
class obj{}
- 声明类时,是不存在
重复声明
的
class obj ;
class obj ;// SyntaxError: Identifier 'obj' has already been declared
静态方法
静态方法的语法
static
关键字为一个类定义了一个静态方法。
静态方法不会在类的实例上被调用,相反被类本身调用。
static 静态方法名称(){方法体}
-
特点
- 静态方法是不会被添加到当前类的实例(创建的对象)中
-
调用
- 通过当前直接调用静态方法
//通过Hero类创建一个hero对象
let hero = new Hero()
console.log(hero);//Hero { name: '张无忌' }
//通过类直接调用静态方法
Hero.sayMe()
静态方法的调用
-
从另一个静态方法调用
- 在同一个类中的一个静态方法调用另一个静态方法,可以使用this关键字。
-
从类的构造函数和其他方法调用
静态方法不能直接在非静态方法中使用this关键字来访问。- 需要使用类名来调用:CLASSNAME.STATIC_METHOD_NAMEO
- 将其作为构造函数的属性来调用该方法:this.constructor.STATIC_METHOD_NAME().
class Hero {
//构造器-创建对象时,初始化的属性和方法
constructor() {
this.name = '张无忌'
this.sayMe = ()=>{
console.log('this is ' +this. name) ;//this is 张无忌
//在构造器中调用静态方法的话,类名直接调用
Hero.sayYou()
}
}
toString(){
console.log('name toString:' + this.name);
}
static sayYou(){
console.log('this is sayYou');
}
static sayHe(){
//当前的静态方法中,调用另一个静态方法
this.sayYou()
}
}
let hero = new Hero()
console.log(hero);
Hero.sayYou()
Hero.sayHe()
类的继承
实现类的继承
extends
关键字用于类声明或者类表达式中,以创建一个类,该类作为另一个类的子类。
class Parent {
constructor() {
this.name = 'parent';
this.sayMe = function () {
console.log('this is sayMe');
}
}
sayYou(){
console.log('this is sayYou');
}
static staticMethod (){
console.log('this is static method.')
}
}
//声明Child类时,指定Child类作为Parent类的子类
class Child extends Parent {
constructor() {
super()//super -> 指向当前子类的父类的构造器
this.age = 18;
}
}
let child = new Child()
console.log(child);
继承的.prototype 必须是一个Object或者null。
继承于内置对象
实现了继承了内置的
Date
对象。
//获取当前年月日
class myDate extends Date {
constructor(){
super();
}
getFormattedDate(){
var months = [ 'Jan','Feb', 'Mar','Apr','May','Jun','Jul','Aug','Sep', '0ct', 'Nov', 'Dec' ];
return this.getDate() + "-" + months[this.getMonth()]+ "-" + this.getFullYear();
}
}
let date = new myDate()
console.log(date.getFormattedDate());//29-0ct-2020
//数组去重
let arr =[1,2,3,4,5,4,3,2,1];
class MyArray extends Array {
constructor(){
super();
}
tochong (array){
return new Set(array);
}
}
var array = new MyArray()
console.log(array.tochong(arr));//Set { 1, 2, 3, 4, 5 }
super关键字
- super 关键字作为函数调用时,代表父类的构造函数。
class A{}
class B extends A{
constructor(){
super()
}
}
super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super 内部的 this指的是B,因此 super()在这里相当于A.prototype.constructor.call(this)。
- super 作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
class A{
p(){return 2}
}
class B extends A{
constructor(){
surper()
console.log(super.p())//2
}
}
let b = new B()
由于 super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super 调用的。