一,前言
1.面向对象的要素
-
类
Class
:定义对象抽象特点,包含它的属性和方法 -
对象
Object
:类的实例,通过
new
生成 - 封装:对数据进行封装
- 继承:子类继承父类
- 多态:由继承而产生了相关的不同的类,对同一个方法可以有不同的响应
- 存取器:用以改变属性的读取和赋值行为
- 修饰符:修饰符是一些关键字,用于限定成员或类型的性质
- 抽象类
- 接口
2.
es6
的
class
并没有实现
多态
,
修饰符
,
抽象类
,
接口
的概念
二,
class
简介
class
1.
JavaScript
语言中,生成实例对象的传统方法是通过构造函数
2.
ES6
提供了更接近传统语言的写法,引入了
Class
类这个概念,作为对象的模板。通过
class
关键字,可以定义类。
3.
ES6
的
class
可以看作只是一个
语法糖
,
新的
class
写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已
4.如下可以看出
class
的类型是一个函数,
class
的原型的
constructor
指向了
class
,这和
es5
的类的概念的现象是一样的
//es5
function Person(name, age) {
this.name = name;
this.age = age;
this.type = "student";
}
Person.prototype.say();
{
console.log("hello");
}
class Person {
constructor(name = "max", age = 21) {
this.name = name;
this.age = age;
this.type = "student";
}
say(){console.log("hello")}
}
let p = new Person(); // Person {name: "max", age: 21, type: "student",__proto__:Object}
typeof Person; // function
Person.prototype.constructor === Person; // true
三,
Class
声明
Class
1.关键字
class
用于声明一个类,
2.
constructor
是类的构造方法,在
new
一个实例对象时自动调用
3.
一个类必须有
constructor
方法,如果没有显式定义,一个空的
constructor
方法会被默认添加
。默认返回当前实例对象。
class Person {
constructor(name = "max", age = 21) {
this.name = name;
this.age = age;
this.type = "student";
}
}
4.使用
new
来实例化一个类的对象,传递的参数会传给类的构造函数
const Lily = new Person('lily',18)
四,静态属性和实例属性
1.
实例属性
:
(1)在
class
中,直接定义在类中的属性,就是实例属性
(2)实例属性在
class
内部可以通过
this
直接访问到,在外部以实例对象的属性访问到
class Person {
name; //实例属性
age;
constructor(name, age) {
this.name = name;
this.age = age;
}
}
let lily =new Person('lily',18)
lily.name //lily
2.
静态属性
(1)
ES6
使用关键字
static
来声明一个静态属性
(2)静态属性指的是
Class
本身的属性,而不是定义在实例对象
this
上的属性,不能被实例访问到,在内部和外部以
Class.propsname
访问到,
class Money {
static total = 100;
constructor() {
console.log("i only have " + Money.total + " yuan");
}
}
console.log(Money.total)
五,静态方法和实例方法
1.
实例方法
:
(1) 直接定义在类上的方法是实例方法,在内部可通过
this
访问,外部使用对象的方法形式
class Money {
save(num) {
console.log("today i store " + num + "yuan");
}
}
const lilysAccount = new Money();
lilysAccount.save(100);
2.
静态方法
:
(1)使用关键字
static
来声明一个静态方法
(2)静态方法指的是
Class
本身的方法,不能被实例访问到,在内部和外部以
Class.methods
访问到,
class Money {
static save(num) {
console.log("today i store " + num + "yuan");
}
}
const lilysAccount = new Money();
lilysAccount.save(100); //报错
Money.save(100) //正确
六,存取器
1.与
ES5
一样,在
class
的内部可以使用
get
和
set
关键字,对某个属性设置
存值函数
和
取值函数
,拦截该属性的存取行为,很灵活,可随意使用
class Person {
_special;
static num = "static value";
set special(val) {
this._special = val > 10 ? 100 : 0;
}
get special() {
return Person.num;
}
}
七,继承
1.在
ES6
中使用
extends
实现继承,如下是继承最简单的模型
class SuperType {}
class SubType extends SuperType {
constructor(){
super()
}
}
2.继承后子类必须在
constructor
方法中调用
super()
为父类构造传递参数方法,否则新建实例时会报错。在这个过程父类也实例化了,这样才确保子类能使用父类的实例属性
3.子类继承父类后,可以使用父类的所有实例属性和实例方法,静态属性和静态方法。实例属性和实例方法没有什么特别,主要讲下静态属性和静态方法
class SuperType {
static Name='father'
static say(){}
}
class SubType extends SuperType {
//作为函数时表示父类构造函数
constructor(){
super()
}
static callFather(){
//super关键字在静态方法中表示父类,即SuperType,用于访问父类的静态属性和静态方法
console.log(super.Name)
super.say()
}
}
4.
super
有两种用法,一种是作为函数,一种作为对象。
(1)作为函数时表示父类构造函数。相当于
SuperType.prototype.constructor.call(this)
(2)作为对象时又分成两种情况,在普通方法中表示父类的原型。在静态方法中表示父类。
八,注意事项
1.类和模块的内部,默认就是严格模式,不存在变量提升。
2.在
ES5
中构造函数是一个函数,可不用
new
来使用。而
class
不使用
new
命令将会直接报错。
3.注意,实例属性没有定义在原型上,属于实例对象的,但是实例方法被定义在原型上,实现复用
4.
class
继承就是寄生组合的语法糖
function object(obj) {
function F() {}
F.prototype = obj.prototype;
return new F();
}
function prototypeInherit(SuperClass, Sub) {
prototype = object(superClass);
prototype.constructor = sub;
Sub.prototype = prototype;
}
function Sub(name, age) {
SuperClass.call(this, name); //重要的一步,相当于es6 class 的 super
this.age = age;
}