目录
一.引入
在我们es5的学习中并没有出现类,那么类是来干什么的呢,主要是解决什么问题呢,那其中又有哪些方法呢,如何去使用?在本篇文章中我会依次给大家介绍,看完这篇文章相信大家对类有了更深层次的理解.
类,顾名思义指类型,一类的意思,在ES6中class(类)作为对象的模块被引入,我们可以通过class关键字定义类,类的本质呢就是function,本质就是构造函数.它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。
二.类
1.类的使用语法
命名类:
class 类名{
//构造函数constructor
constructor(){
}
//constructor同级的函数----原型成员
方法(){
}
//静态成员
stactic 方法(){
}
}
匿名类:
let Example = class {
//构造函数constructor
constructor(){
}
//constructor同级的函数----原型成员
方法(){
}
//静态成员
stactic 方法(){
}
}
注意:
- constructor是在创建实例时自调用 , 一个类必须存在constructor构造方法(作用:创建实例对象的属性 ) 如果不写则系统默认添加 constructor(){}
- 创建实例对象后,构造方法会被自动调用,我们不要去调用它,其中隐式参数this指向新创建的实例对象, 最后把实例对象的引用值返回
- 类中的方法都是定义在类的原型上
- 类的实例调用的方法都是调用原型上的方法
- 类的内部定义的方法都是不可枚举的
2.方法
(1)constructor方法
constructor 方法是类的默认方法,创建类的对象时被调用。也被称为类的构造方法(构造函数、构造器)。一个类中有且仅有一个构造方法。在new 类()时将执行constructor方法
class People {
constructor() {
console.log("我是构造方法,使用new创建对象时调用");
}
}
new People(); //将执行constructor方法
(2)原型方法
不需要使用function关键字,通过“对象.原型方法”调用。
class People {
say(world) {
console.log(`say ${world}`);
}
add(a, b) {
console.log(a + b);
}
}
let p = new People();
p.say("hello"); //say hello
p.add(1, 2); //3
(3)静态方法
使用static修饰,调用时不需要创建对象,直接通过“类名.静态方法”调用
class People {
static sum(a, b) {
console.log(a + b);
}
}
People.sum(1, 2);
3.static
- static只能通过类来访问。即static只能通过类自身来调用,不能通过类的实例来调用。
- 静态方法调用同一个类中的其他静态方法,可使用 this 关键字。
- 非静态方法中,不能直接使用 this 关键字来访问静态方法。而是要用类名来调用;或者用构造函数的属性来调用该方法。
4.ES5构造函数与ES6类的区别
首先我们先书写一个构造函数:代码如下
<script>
//构造函数
function Person(name,age){
//实例成员name,age
this.name=name;
this.age=age;
}
//原型对象Person.prototype
//原型成员like
Person.prototype.like=function(){
console.log(this.name+"喜欢小狗狗");
}
//实例对象p
var p=new Person("小明",18);
//构造函数上的属性和方法(静态成员)----eat
Person.eat=function(){
console.log("重庆小面");
}
console.log(p);
p.like();//小明喜欢小狗狗
//静态成员只能给构造函数使用不能给实例使用
Person.eat();//重庆小面
p.eat();//报错
</script>
再来写一个类class,代码如下
<script src="">
//class类
class Person {
// 构造函数
constructor(name, age) {
this.name = name;
this.age = age
}
//原型成员 like constructor
like(){
console.log(this.name + "喜欢小狗狗")
}
//静态成员 eat
static eat(){
return "重庆小面"
}
}
var p=new Person("小明",18);
console.log(p);
</script>
通过观察我们发现类本质就是一个构造函数,类的写法用一个函数也就是一个花括号包含了实例成员,构造函数,原型成员,静态成员全包含在内,它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法
三.类的继承
1.类的继承
(1)语法:
class 子类 extends 父类{
constructor(参数){
super(参数);
}
}
其中extands类似于原型链继承,super类似于构造函数继承,里面的参数给父类进行传参
(2)代码解析
<script>
class People {
//父类构造方法
constructor() {
this.a = 100; //父类中定义的变量
console.log("People constructor");
}
//原型方法
eat() {
console.log("eat...")
}
//静态方法
static play() {
console.log("play...")
}
}
class Student extends People {
//子类构造方法
constructor() {
super(); //调用父类构造器,必须存在,且位于子类构造器第一行的位置
this.b = 200; //子类定义的变量
console.log("Student constructor");
}
study() {
console.log("study...");
}
}
let stu = new Student();
console.log(stu.a,stu.b);//100,200
stu.eat();//eat...
stu.study();//study...
Student.play();//play...
</script>
通过上面的代码我们发现:
- new出来的新对象可以调用子类的原型方法和父类的原型方法
- constructor方法在new 类()时将执行constructor方法
- 子类可以调用父类的静态方法
2.类的继承注意事项
-
解决代码的复用
-
使用extends关键字实现继承
-
子类可以继承父类中所有的方法和属性
-
子类只能继承一个父类(单继承),一个父类可以有多个子类
-
子类的构造方法中必须有super()来指定调用父类的构造方法,并且位于子类构造方法中的第一行,
-
子类中如果有与父类相同的方法和属性,将会优先使用子类的(覆盖)强调!!!!
3.创建子类对象的过程
- 创建父类对象
- 再追加子类对象空间
- 子类构造方法自动执行, 子类构造方法中使用super(...)调用父类构造方法, super(...)位于this使用之前
- 反回子类对象的引用(如果父类没有写constructor,子类使用super(), 父类的构造方法无参数也使用super(), 父类构造函数有参数,则super(实参...) )
4.内部类
内部类属于外部类的成员,必须通过“外部类.内部类”访问
// 外部类
class Outer {
constructor() {
console.log("outer");
}
}
// 内部类
Outer.Inner = class {
constructor() {
console.log("Inner");
}
}
new Outer.Inner();
5.super总结
super既可以作为函数使用又可以作为对象使用,在这两种情况下,它的用法完全不同
- 情况一:super作为函数使用时,代表的是父类的构造函数,调用后返回的是子类的实例(super内部的this指向子类的实例)
- 注意只能在子类的构造函数中调用
情况二:super作为对象使用
- 1.在普通方法中,super指向父类的原型对象,super调用的方法中的this指向子类的实例
- 2.在静态方法中,super指向父类,super调用的方法中的this指向子类,子类中定义了构造函数,那么它必须先调用 super() 才能使用 this。
子类任何方法中都可以使用super.父类成员 访问到父类中被重写的成员。