1. 封装
传统面向对象的编程序语言都是【类】的概念,对象都是由类创建出来,然而早期 JavaScript 中是没有类的,面向对象大多都是基于构造函数和原型实现的,但是 ECMAScript 6 规范开始增加了【类】相关的语法,使得 JavaScript 中的面向对象实现方式更加标准。
class(类)是 ECMAScript 6 中新增的关键字,专门用于创建类的,类可被用于实现逻辑的封装。
javascript
// 创建类
class Person {
// 此处编写封装逻辑
}
// 实例化
let p1 = new Person()
console.log(p1)
1.1 实例成员
javascript
// 创建类
class Person {
// 实例属性
name = '小明';
// 实例方法
sleep () {
console.log('sleeping...')
}
}
// 实例化
let p1 = new Person();
p1.sayHi();
总结:
-
关键字 **
class
**封装了所有的实例属性和方法 -
类中封装的并不是变量和函数,因此不能使用关键字
let
、const
或var
1.2 静态成员
javascript
// 创建类
class Person {
// 静态属性
static version = '1.0.0';
// 静态方法
static getVersion = function () {
console.log(this.version);
}
}
// 静态方法直接访问
console.log(Person.version);
Person.getVersion();
总结:
-
**
static
**关键字用于声明静态属性和方法 -
静态属性和方法直接通过类名进行访问
1.3 构造函数
创建类时在类的内部有一个特定的方法 constructor
,该方法会在类被实例化时自动被调用,常被用于处理一些初始化的操作。
javascript
class Person {
// 实例化时 立即执行
// 构造函数、构造方法、构造器
constructor (name, age) {
this.name = name;
this.age = age;
}
// 实例方法
walk () {
console.log(this.name + '正在走路...');
}
}
// 实例化
let p1 = new Person('小明', 18);
p1.walk();
总结:
- **
constructor
**是类中固定的方法名 - **
constructor
**方法在实例化时立即执行 - **
constructor
**方法接收实例化时传入的参数 - **
constructor
**并非是类中必须要存在的方法
2. 继承
2.1 extends
**extends
**是 ECMAScript 6 中实现继承的简洁语法,代码如下所示:
javascript
class Person {
// 父类的属性
legs = 2;
arms = 2;
eyes = 2;
// 父类的方法
walk () {
console.log('人类都会走路...');
}
// 父类的方法
sleep () {
console.log('人都得要睡觉...');
}
}
// Chinese 继承了 Person 的所有特征
class Chinese extends Person {}
// 实例化
let c1 = new Chinese();
c1.walk();
如上代码所示 extends
是专门用于实现继承的语法关键字,Person
称为父类、**Chinese
**称为子类。
2.2 super
在继承的过程中子类中 constructor
中必须调 super
函数,否则会有语法错误,如下代码所示:
javascript
class Person {
// 构造函数
constructor (name, age) {
this.name = name;
this.age = age;
}
// 父类的属性
legs = 2;
arms = 2;
walk () {
console.log('人类都会走路...');
}
}
// 子类 English 继承了父类 Person
class English extends Person {
// 子类的构造函数
constructor (name, age) {
super(name, age);
}
// 子类的属性
skin = 'white';
language = '英文';
}
// 实例化
let e1 = new English('jack', 18);
console.log(e1.name);
子类构造函数中的 **super
**函数的作用是可以将子类实例化时获得的参数传入父类的构造函数之中。
ECMAScript 6 中基于类的面向对象相较于构造函数和原型对象的面向对象本质上是一样的,基于类的语法更为简洁,未来的 JavaScript 中也都会是基于类的语法实现,当前阶段先熟悉基于类的语法,后面课程中会加强基于类语法的实践。
3. JavaScript 中逗号与分号的问题
-
分号
- JavaScript 中分号 ; 代表了一个语句的结束,JavaScript 默认将换行符当做了分号,所以可以省略不写
-
对象为什么用逗号,而不是分号?
-
因为对象 p 里的 属性: 属性值不是一个语句,一整个 let p = {} 才是一个语句,所以最后用的是分号(;)结尾
-
如果 属性: 属性值, 后面还有 属性2: 属性值2,的话,如果省略了逗号,那么 JavaScript 就会默认将换行符当做了分号,所以就会报错。
-
- 函数、构造函数、class 类里为什么又用分号呢?
- 函数体的每一行就是一条执行语句,所以使用分号,JavaScript 默认将换行符当做了分号,所以可以省略不写。
- 构造函数也是函数,所以同理。
- class 类相当于构造函数,里面的每一个行都相当于一个语句,所以使用分号(;),JavaScript 默认将换行符当做了分号,所以也可以省略不写。