TS中的类:
- 创建类实例
- constructor方法
- 取值函数和存值函数
- class表达式
- 静态方法
- 实例属性其他写法
- 实现私有方法
ES5中创建类实例
function Point(x, y){
this.x = x
this.y= y
}
Point.prototype.getPosition = function(){
return '(' + this.x + ' , ' + this.y +')'
}
var p1 = new Point(2,3)
console.log(p1.getPosition()) //(2 , 3)
ES6中创建实例
class Point1 {
x: number
y: number
constructor(x, y) {
this.x = x
this.y = y
}
getPosition() {
return '(' + this.x + ' , ' + this.y +')'
}
}
const p2 = new Point1(2,3)
console.log(p2.getPosition()) //(2 , 3)
ES5中的取值函数和存值函数
var userInfo = {
_age: 18,
set age(newValue){
if(newValue>18){
console.log('年纪很大了')
}else{
console.log('还年轻,哈哈')
}
},
get age(){
console.log('年纪是---')
return this._age
}
}
console.log(userInfo.age) //年纪是--- 18
userInfo.age = 16 //还年轻,哈哈
ES6中的取值和存值函数
class userInfo1 {
_age:number
constructor(age){
this._age = age
}
set age(newValue){
if(newValue>18){
console.log('年纪是---')
}else{
console.log('还年轻,年纪是---')
}
}
get age(){
console.log('获得的年纪是---')
return this._age
}
}
const userInfo2 = new userInfo1(18)
console.log(userInfo2.age) //获得的年纪是--- 18
userInfo2.age = 20 //年纪是---
//class的另一种写法
const class1 = class c {
constructor(){
}
}
const class2 = new class1()
静态方法和静态属性
class Point2 {
x: number
y: number
static z:number = 10
constructor(x, y) {
this.x = x
this.y = y
console.log('target---',new.target)
}
getPosition() {
return '(' + this.x + ' , ' + this.y +')'
}
static getClassName(){
return Point2.name //es5中的方法,可以直接返回类的名称
}
}
const point3 = new Point2(2,4) //初始化时可以拿到target里的信息,如下:
// target--- class {
// constructor(x, y) {
// this.x = x;
// this.y = y;
// console.log("target---", new.target);
// }
// getPosition() {
// return "(" + this.x + " , " + this.y + ")";
// }
// static getClassName() {
// …
// console.log(point3.getClassName()) //这样写会报错
console.log(Point2.getClassName()) //_Point2
console.log(Point2.z) //10
ES5中的类的继承
function Food(){
this.type = 'food'
}
Food.prototype.getType = function(){
return this.type
}
function Vegetable(name){
this.name = name
}
Vegetable.prototype = new Food()
const tomato2 = new Vegetable('tomato')
console.log(tomato2.getType()) //food
ES6中的继承
class Parent {
name: string
constructor(name){
this.name = name
}
getName(){
return this.name
}
static getNames(){
return this.name
}
}
class Child extends Parent{
age:number
constructor(name,age){
super(name)
this.age = age
}
}
const child1 = new Child('lyy',18)
console.log(child1)
console.log(child1.getName()) //lyy
console.log(child1 instanceof Child) //true
console.log(child1 instanceof Parent) //true
console.log(Child.getNames()) //Child
关于super
1.super作为函数,ES6中要求,子类中构造函数必须调用一次super()函数
2.super作为对象,在普通方法中指向父类的原型对象,在静态方法中指向父类
class Parent1{
type: string
static getType: () => string
constructor(){
this.type = 'parent'
}
getName(){
return this.type
}
}
Parent1.getType = () => {
return 'is parent'
}
class Child1 extends Parent1{
constructor(){
super()
console.log('constructor:'+super.getName())
}
getParentName(){
console.log('getParentName:'+super.getName())
}
static getParentType(){
console.log('getParentType:'+super.getType())
}
}
const c1 = new Child1() //constructor:parent
c1.getParentName() //getParentName:parent
Child1.getParentType() //getParentType:is parent
//如果在子类里对同样的数据进行赋值,看一下效果
class Child2 extends Parent1{
constructor(){
super()
console.log('constructor:'+super.getName())
this.type = 'lyy'
}
getParentName(){
console.log('getParentName:'+super.getName())
}
static getParentType(){
console.log('getParentType:'+super.getType())
}
}
const c2 = new Child2() //constructor:parent
c2.getParentName() //getParentName:lyy
Child1.getParentType() //getParentType:is parent
//原生函数的继承(ES6中可以)。原生函数包括:Boolean, Number, String, Array, Date, Function, RegExp, Error, Object
class CustomArray extends Array {
constructor(...args){
super(...args)
}
}
const array1 = new CustomArray(3)
array1.fill(3)
console.log(array1) //CustomArray(3) [3, 3, 3]
注意:
ES6的类和ES5的构造函数,这两种形式在实现继承的机制上存在差异。
ES5继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上;
而ES6的继承是先创建父类的实例对象this(所以必须先调用父类的super()方法),然后再用子类的构造函数修改this。super关键字指代父类的实例,即父类的this对象。在子类构造函数中,调用super后才可以使用this关键字,否则报错。
TS中的类:
//ts中的语法
class Point3 {
public x: number
public y: number
constructor(x:number, y:number) {
this.x = x
this.y = y
}
getPosition() {
return '(' + this.x + ' , ' + this.y +')'
}
}
修饰符(public, private, protected)
//private
class Parent2 {
private age: number
constructor(age: number){
this.age = age
}
}
const p = new Parent2(18)
// p.age 报错,只能在Parent2内部使用
class child2 extends Parent2{
constructor(age: number){
super(age)
// console.log(super.age) 报错,这里不能访问父类的私有属性
}
}
//protected
class Parent3 {
protected age: number
constructor(age: number){
this.age = age
}
protected getAge() {
return this.age
}
}
const p3 = new Parent3(18)
// p3.age 报错,只能在Parent3内部以及子类中使用
class child3 extends Parent3 {
constructor(age: number) {
super(age)
console.log('Parent3',super.age) //子类中不能直接访问父类的protected属性,但是可以访问protected方法
console.log('Parent3 method',super.getAge())
}
}
const child4= new child3(20)
//Parent3 undefined
//Parent3 method 20
父类的构造方法中如果添加了protected,如下:
class Parent3 {
protected age: number
protected constructor(age: number){
this.age = age
}
protected getAge() {
return this.age
}
}
// const p3 = new Parent3(18) 这里会报错
此时就不能直接通过父类的构造函数生成实例了,只能通过子类的构造函数生成实例
只读属性readonly
class UserInfo3 {
readonly name: string
constructor(name: string){
this.name = name
}
}
const userInfo4 = new UserInfo3('lyy')
// userInfo4.name = 'lllll' 报错,readonly属性不可修改
静态属性static
class Parent4 {
public static getAge(){
return Parent4.age
}
private static age: number = 180
constructor(){
}
}
const p4 = new Parent4()
console.log(Parent4.getAge()) //只能在通过父类访问
可选属性
class userInfo {
public name: string
public age?: number
constructor(name: string, age?: number, public sex?: string){
this.name = name
this.age = age
}
}
const info1 = new userInfo('lyy')
console.log(info1). //userInfo {sex: undefined, name: 'lyy', age: undefined}
存取属性
class userInfo2 {
private _address: string
constructor(){
}
get address() {
return this._address
}
set address(value){
this._address = value
}
}
const info2 = new userInfo2()
info2.address='asdg'
console.log(info2.address) //asdg
抽象类
abstract class People {
constructor(public name: string) {
}
public abstract printName(): void
}
class Man extends People{
constructor(name: string){
super(name)
this.name = name
}
public printName() {
console.log(this.name)
}
}
const m1 = new Man('lyy')
m1.printName() //lyy
//使用abstract标记属性和存取器
abstract class People1 {
abstract _name: string
abstract get name(): string
abstract set name(value: string)
}
class Man1 extends People1{
_name: string
get name(): string {
return this._name
}
set name(value: string) {
this._name = value
}
}
类可以多次赋值不同的类型
class People2 {
constructor(public name: string){
}
}
class Animal {
constructor(public name: string){
}
}
let p1:People2 = new People2('people')
p1 = new Animal('animal')
//所以要用instanceof判断类的类型,因为一个类可以多次赋值不同的类型
//接口的实现
interface Food {
type: string
name: string
}
class FoodInfo implements Food{
type: string
name: string
}
注意:
接口继承类,会继承这个类的成员但是不包括其实现,也就是说只继承这个成员及其类型。接口还会继承private和protected修饰的成员,当接口继承的类中包含这两个修饰符修饰的成员变量时,该变量只能被这个类以及子类实现
class A {
protected name: string
}
interface I extends A {
}
class B implements I {
public name: string // 这里有name属性依然会报错,因为B必须要继承A
}
class C extends A implements I {
public name: string // 直接继承就可以
}
泛型中使用类类型
// 这里的new()表示调用这个类的构造函数,返回的类型即创建的实例的类型
const create = <T>(c: new() => T): T =>{
return new c()
}
class Infos {
public age: number
constructor(){
this.age = 18
}
}
console.log(create(Infos)) //Infos {age: 18}
console.log(create(Infos).age) //18