javascript中面向对象
avaScript有一个基于原型的、面向对象的编程模型
它使用其他对象作为原型创建对象,并实现继承,它操作所谓的原型链,其实在javascript没有类的概念,在es6中才开始引入关键字class,当然在es6中也是用构造函数和原型链,只是在语法上更清晰,本质上还是和es5相同
==TypeScript支持ES6类语法,但也添加了一些其他特性,比如访问修饰符和接口,因此在这边,我们将用TypeScript而不是纯ES6。==
Class
类是创建具有特定功能和属性的对象,一个基本的类:
class Person {
firstName = "";
lastName = "";
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
name() {
return `${this.firstName} ${this.lastName}`;
}
whoAreYou() {
return `Hi i'm ${this.name()}`;
}
}
1、定义一个类需要用class关键词声明
2、可以像firstName那样描述类属性
3、每一个类都要有一个特殊的函数就是构造函数,在创建实例的时候被调用,constructor声明
4、声明对象方法,可以像name()一样声明
5、在方法中,this指向类实例。
类实例
类是创建实例对象的原型,实例化类也可以es5一样用new关键字,在实例的时候会调用constructor构造函数,可以通过构造函数传参去初始化属性或者调用方法
let asim = new Person("Asim","Hussain");
上面这样就创建类一个实例
asim实例有许多属性和方法,在Person类中定义的,可以在实例中被调用
let asim = new Person("Asim","Hussain");
asim.whoAreYou()
// "Hi i'm Asim Hussain"
继承
一个类可以继承来自另一个类,我么可以创建一个类通过继承的方法添加属性和方法
我们用extends关键字
class Student extends Person {
course;
constructor(firstName, lastName, course) {
super(firstName, lastName);
this.course = course;
}
whoAreYou() {
return `${super.whoAreYou()} and i'm studying ${this.course}`;
}
}
1、使用继承关键字extends去继承父类Person的属性和方法,在es
以前,继承一般使用混合继承方式
2、我们能添加自己的属性,如course
3、可以用super方法调用父类的构造方法,如:super(firstName,lastName)
4、我们可以重写从父类继承下来的方法,如:whoAreYou()
5、在模板方法中,super指的是父类实例
我们可以实例化Student:
let asim = new Student("Asim", "Hussain", "Angular 6");
console.log(asim.whoAreYou());
// Hi i'm Asim Hussain and i'm studying Angular 6
访问修饰符
到现在为止,上面的都是纯es6的语法,但是接下来就开始补充typescript语法,TypeScript 添加了很多很好的功能在ES6 class的基础上,就是通过访问修饰符来装饰方法和属性的可见性
如下例子,通过private在装饰属性:
class Person {
private firstName = "";
private lastName = "";
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
如果我们在Student中去创建一个方法,并且去访问继承父类的属性
class Student extends Person {
.
.
.
test() {
console.log(this.firstName);
}
}
然后我们实例化Student类,并调用test方法
let asim = new Student("Asim", "Hussain", "Angular 2");
console.log(asim.test());
执行完后会发现,报错了
error TS2341: Property 'firstName' is private and only accessible within class 'Person'.
这就是访问修饰符,private的修饰符只允许在Person的类方法中可访问
除了private访问修饰符以外,还有三个访问修饰符
Public
这是默认值,意味着它到处可见
private
只有它所声明的类的成员方法才能访问
protected
只有它声明的类和从该类继承的任何类才能可以访问
构造函数
在构造函数中,最常用的就是通过构造函数初始化属性值
class Person {
private firstName = "";
private lastName = "";
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
其实,通过访问修饰符装饰,以上方法可以缩写为
class Person {
constructor(private firstName, private lastName) {
}
}
接口
typescript还提供了接口的功能,它一般和class一起结合起来使用,在类中实现接口,如下:
class Person implements Human {
}
以上代码所示,Human是一个接口,一个接口定义了继承他的类最少需要实现多少属性和方法,也可以说,接口给类定义规则,凡是实现这个接口的类,必须实现接口中的方法和属性,所以Human我们可以定义为:
interface Human {
firstName: string;
lastName: string;
}
==因为接口都是提供类实现的,所以不能具有访问修饰符,必须是public==
如果类中没有实现接口中的所有方法和属性,那么将会报错:
error TS2420: Class 'Person' incorrectly implements interface 'Human'. Property 'firstName' is missing in type 'Person'.
当然有的时候需要让接口中的一些方法或者属性是可选的,增加接口的灵活性,那么可以在方法或者属性名后面加上?以表示这个是可选的
firstName: string;
lastName: string;
name?: Function;
isLate?(time: Date): Function;
}
总结
在es6中,我们有一种新的关键字class来定义一个类;
我们可以继承方法和属性在一个类中,使用extends关键字继承;
其实本质上,还是使用原型链的方式继承,只是给了更好理解的语法糖;
Typescript在class的基础上添加了访问修饰符和接口