类的声明:
在 ES6 之前其实是不存在类的,因为 JavaScript 并不是一门基于类的语言,它使用函数来创建对象,并通过原型将它们关联在一起。
我们来看个 ES5 语法的近类结构,首先创建一个构造函数,然后定义另一个方法并赋值给构造函数的原型。
function MyClass(num){
this.num = num;
this.engines = false;
}
MyClass.prototype.start = function(){
console.log("starting...");
this.engines = true;
};
const myclass = new MyClass(1);
myclass.start();
MyClass 是一个构造函数创建了MyClass类型对象.
使用this声明并初始化MyClass 的属性num 和 engines
在原型中存储了一个可供所有实例调用的方法start
使用"new+"的构造方法实现创建实例对象myclass 最后调用start方法.
在ES6中提供了class创建方法:
class Clothes{
constructor(color,size){
this.size = size;
this.color = color;
}
}
const lan = new Clothes("蓝","L");
const bai = new Clothes("白","XL");
在上面代码中 constructor
是类的构造函数,它是定义类的默认方法,当你使用 new 来创建对象实例化时,会自动调用该方法。如果没有在类中添加 constructor
,也会默认有一个 constructor
方法,所以它在类中是必须有的。
用class关键字改造MyClass函数
function MyClass(num){
this.num = num;
this.engines = false;
}
MyClass.prototype.start = function(){
console.log("starting...");
this.engines = true;
};
const myclass = new MyClass(1);
myclass.start();
//
class Myclass{
constructor(num){
this.num = num;
this.engines = false;
}
start(){
console.log("starting...");
this.engines = true;
}
}
const myclass = new MyClass(1);
myclass.start();
类和函数有两种存在形式:
声明形式:function\class
表达式形式:const A = class{}
创建一个狗的类型(ES6写法)
function Dog(name){
this.name = name;
}
Dog.prototype.sayName = function(){
console.log(this.name);
};
let dog = new Dog("柯基");
dog.sayName();
console.log(dog instanceof Dog);
匿名类写法:
let Dog = class{
construcor(name){
this.name = name;
}
sayName(){
console.log(`${this.name}`);
}
};
let dog = new Dog("柯基");
dog.sayName();
命名类表达式:
let Dog = class MyClass{
constructor(name){
this.name = name;
}
sayName(){
console.log(this.name);
}
};
类可以在类表达式中命名类名,类名不能在类的外使用.
ES6中提供了继承关键字extends
class child_class_name extends parent_class_name {}
上面代码的意思是 child_class_name
类继承了 parent_class_name
类。
class Animal{
constructor(name,age,apeed){
this.name = name;
this.age = age;
this.speed = speed;
}
run(){
console.log(`${this.name}🐕${this.age}岁了,跑了${this.speed}的速度`);}
stop(){
consle.log(`${this.name}停止了奔跑。`);
}
}
class Dog extends Aniaml{}//Dog类继承了Animal类
//实例化狗
let dog = new Dog("柯基","1",5);
dog.run();
dog.stop();
ES6 为我们提供了超级函数 super 我们的继承变得完整且具备可扩展性。
super.method(...)调用父级方法
super(...)调用父构造方法
在 JavaScript 中,继承类的构造函数和其他函数是有区别的。继承类的构造函数有一个特殊的内部属性
[[ConstructorKind]]:"derived"
。通过该属性会影响 new 的执行:
- 当一个普通(即没有父类的类)的构造函数运行时,它会创建一个空对象作为 this,然后继续运行。
- 但是当子类的构造函数运行时,与上面说的不同,它将调用父构造函数来完成这项工作。
所以,继承类的构造函数必须调用 super() 才能执行其父类的构造函数,否则 this 不会创建对象。
这里会给大家介绍以下两种类的属性和方法:
- 静态方法
- 静态属性
- 私有方法
- 私有属性
静态方法:好处是不需要实例化,可以直接通过类名访问,不需要消耗资源反复创建
//Es5语句
function Dog(name){
this.name = name;
}
Dog.create = function(name){
return new Dog(name);
};
Dog.prototype.sayName = function(){
console.log(`${this.name}`);
};
let dog = Dog.create("柯基");
dog.sayName();
上述代码解析如下:
- 创建一个构造函数
DogType
。 - 以“类名.方法名”的方式为其定义一个静态方法
create
,该方法最终创建一个DogType
实例。 - 在其原型上添加
sayName
方法。 - 使用“类名.方法名”的方式调用其静态方法
create
创建一个实例对象dog
。 - 使用
dog
调用sayName
方法输出自我介绍的信息。
由于 create
方法可以直接通过类名去访问,不需在被实例化时创建,因而可以被认为是 DogType
类的一个静态方法。
在ES6中提供了static关键字定义静态方法.
static methodName(){
}
有一点需注意一下,如果静态方法中包含 this 关键字,这个 this 关键字指的是类,而不是实例。
没有创建实例化对象,直接用「类名.方法名」就可以访问该方法,这就是静态方法的特点了。除了这个特点外,静态方法不能被其实例调用,我们来试试。
class MYClass{
static method1(){
this.method2();
}
static method2(){
console.log("hello");
}
}
let myClass = new MyClass();
myclass.method2();
可以看到使用 myclass
实例对象调用 method2
静态方法会报错,则说明静态方法只能通过“类名.方法名”调用.
静态属性具有全局唯一性,静态属性只有一个值,任何一次修改都是全局性的影响。
当我们类中需要这么一个具有全局性的属性时,我们可以使用静态属性。
class Dog{
static dogName = "柯基";
}
console.log(Dog.dogName);
在上面的代码中,我们使用 static 关键字给 Dog
类定义了一个名为 dogName
的静态属性。
静态方法和静态属性是可以被继承的