JS中的类
作为一个前端小白白,本篇将从最基础的部分来说~
前言
大多数面向对象的编程语言都支持类和类继承的特性,而JavaScript却不支持这些特性,因为JavaScript的创造者在设计JS语言时并没有借鉴从C, Java中关于类的部分,Javascript语言实际上是(简化的)函数式编程+(简化的)面向对象编程的混合产物,它不是真正的面向对象编程(OOP)语言,它的语法最初并没有class
(类)。从ES1到ES5,开发者们都在使用着各种方法来实现类似的类特性,终于在ES6中引入了类的特性。
面向对象
要理解类,我们首先需要了解面向对象编程的思想。
面向对象(Object Oriented)是一种新兴的程序设计方法,或者是一种新的程序设计规范(paradigm),其基本思想是使用对象、类、继承、封装、多态等基本概念来进行程序设计。从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。
对象
对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务(方法)组成。
类的实例化可生成对象,一个对象的生命周期包括三个阶段:生成、使用、消除。
类
类是具有相同属性和方法的一组对象的集合,它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和方法两个主要部分。在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属性和方法两个主要部分。
ES5中类的实现
ES5及早期版本中没有类的概念,实现近似类的方法就是创建一个自定义类型,首先创建一个构造函数,里面定义了类的属性,类的方法通过赋值给构造函数的原型来定义。最后,通过new
操作符来创建一个类的实例,也就是对象。
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
//给构造函数的原型添加方法
Person.prototype.running = function() {
console.log(this.name + this.age + "running");
}
//实例化对象
var p = new Person("blend", 18);
p.running();
ES5中的继承
ES5的继承需要多个步骤才能实现,如下例:
// Shape - 父类(superclass)
function Shape( length,width) {
this.length =length ;
this.width = width;
}
// 父类的方法
Shape.prototype.getArea = function() {
return this.length*this.width
};
// Rectangle - 子类(subclass)
function Rectangle(length) {
Shape.call(this,length,length); // call super constructor.
}
// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
console.log('Is rect an instance of Rectangle?',
rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
rect instanceof Shape); // true
rect.getArea(1, 1); // Outputs, '1'
ES6中的类
ES6中引入了类的特性,可以直接使用class关键字进行类声明,但实际上ES6的类声明只是基于ES5中自定义类型声明的语法糖,typeof
Person 最终返回的结果是 function ,所以ES6中的类声明实际上创建了一个具有构造函数方法行为的函数。👉深入理解 JavaScript 中的 class
class Person {
//等价于ES5中的构造函数
constructor(name, age) {
this.name = name;
this.age = age;
}
//等价于Person.prototype.running
running() {
console.log(this.name + this.age + "running");
}
//静态方法
static create(name,age){
return new Person(name,age)
}
}
const p = new Person("blend", 18);
p.running();
⚠️特点:
-
在类中所有的方法都是不可以枚举的
-
必须通过关键字new来调用函数
-
可以使用static关键字来定义静态成员,静态方法只能通过类来直接调用,不能通过实例对象来调用
ES6中的继承
ES6中使用extends关键字来指定类继承的函数,使用super()方法即可以访问父类的构造函数。
//父类
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
running() {
console.log(this.name, this.age, "running");
}
}
//子类
class Student extends Person {
constructor(name, age, sno, score) {
super(name, age);
this.sno = sno;
this.score = score;
}
studying() {
console.log(this.name, this.age, this.sno, this.score, "studing");
}
}
const stu = new Student1("why", 18, 110, 100);
stu.studying();
❗️ 注意:
- 在constructor中,子类必须通过super来调用父类的构造方法,对父类进行初始化,否则会报错。
- 在构造函数访问this之前一定要调用super( ),它负责初始化this。
私有变量
ES6 中 class 的出现拉近了 JS 和传统 OOP 语言的距离。但是在其中,比较大的一个问题就是私有变量问题,私有变量就是只能在类内部访问的变量,外部无法访问的变量。ES6中如何实现?
可以参考下面这些博客来读一读: