Typescript1
// //类型为number
// let a:number
// //只可以是数字
// a=10
// //如果变量的声明和赋值同时进行的,ts可以自动对变量进行类型检测
// let c = false
// c = true
//:number返回值是number
// function sum(a:number,b:number):number{
// return a + b
// }
// let result = sum(1,2)
/* //联合类型
let b :string|number
b = '2'
b = 2 */
//any任意类型
//unknown 表示未知类型 ,不可以赋值给其他类型,就是安全类型的any
//断言
// <类型> 变量
// 变量 as 类型
//void 表示没有返回值
// function fn() : void{
// }
//never 永远不会返回结果
//{}用来指定对象中可以包含哪些属性
//语法:{属性名:属性值,属性名:属性值}
// let b:{name:string}
// // ?:可选属性
// let c :{name:string,age?:number}
// c = {name:'haha'}
// //[任意变量名:string] :any 表示任意类型属性
// let c:{name:string,[propName:string]:any}
// c= {name:'123213',age:12,gener:'男'}
// let d:(a:number,b:number) =>number=function (a:number,b:number):number{
// return a
// }
// var funcType1=function(name:string,age:number):number{
// return age
// }
//元组 就是固定长度的数组
//语法 [类型,类型,类型]
// let h : [string,number]
// h = ['1',2]
/* enum Gender{
Male = 0,
Female = 1
}
let i :{name:string,gender:Gender}
i={
name : '北方',
gender:Gender.Male
}
console.log(i.gender === Gender.Male)
*/
/*
面向对象
*/
/*
直接定义的属性是实例属性,需要通过对象的实例去访问
const per = new Person()
per.namel
使用static开头的属性是静态属性(类属性)可以直接通过类去访问
Person.age
readonly开头为只读属性
*/
/* //使用class关键字定义一个类
//对象中主要包含两部分 属性 方法
class Person{
//定义实例属性 这种属性new后才能看到
// name :string = '猴子'
name = '猴子'
//在属性前使用static关键字可以定义雷属性(静态属性)
static age : number = 19
//定义方法 实例
sayHi(){
}
//static开头类方法
static sayHello(){
}
}
const per = new Person()
//静态属性就去用类去访问,不要创建对象
console.log(Person.age)
per.sayHi() */
//构造函数
// class Dog{
// // name = '旺财'
// // age = 18
// name :string
// age :number
//constructor被称作构造函数
//构造函数会在对象创建时调用
//调用new Dog的时候就是调用constructor
//传参
// constructor(name:string,age:number){
// //在实例方法中,this就表示当前实例
// //此时this就是dog
// //console.log(this)
// //在构造函数中当前对象就是当前新建的那个对象
// //可以通过this向新建的对象添加属性
// this.name = name
// this.age = age
// }
// bark(){
// console.log(this)//谁调用this指向谁
// console.log(this.name)//谁调用的,this就点谁
// }
// }
// //创建一个实例
// const dog = new Dog('hah',2)
// const dog2 = new Dog('hh',3)
//继承
//此时animal被称作父类,dog被称作子类
//使用继承后,子类将会拥有父类所有的方法和属性
//通过继承可以将多个类中共有的代码写在一个父类中
//这样只需要写一次即可让所有的子类都同时拥有父类中的属性和方法
//如果希望在子类中添加一些父类没有的属性或者方法直接添加
//定义一个类
// class animal{
// name:string
// age:number
// constructor(name:string,age:number){
// this.name = name
// this.age = age
// }
// sayHi(){
// console.log('叫')
// }
// }
// //使dog继承animal
// class dog extends animal{
// //在父类基础上添加自己的功能
// run(){
// console.log('hahah')
// }
// //如果在子类中添加和父类一样的方法,会在子类中覆盖之前继承的父类方法
// //这种子类覆盖父类方法的形式,我们称其为重写
// sayHi() {
// console.log('汪汪汪')
// }
// }
// class cat extends animal{
// }
// var Dog = new dog('hahah',13)
// var Cat = new cat('123',19)
// console.log(Dog)
// Dog.sayHi()
// Dog.run()
// console.log(Cat)
// Cat.sayHi()
//super 代表父类
/* (
function (){
class Animal{
name:string
constructor (name:string){
this.name = name
}
sayHello(){
console.log('叫')
}
}
class Dog extends Animal{
age : number
//如果在子类中写了构造函数,在子类构造函数中必须对父类的构造函数进行调用
constructor(name:string,age:number){
super(name)//调用父类构造函数,父类构造函数有参数,所以传进去
this.age = age
}
sayHello() {
//在类的方法中super就表示当前类父类
//super.sayHello()
console.log('wang')
}
}
const dog = new Dog('hahha',18)
dog.sayHello()
}
)() */
//抽象类
/*
以abstract开头的类是抽象类
抽象类与其他类区别不大,只是不可创建对象实例
抽象类就是专门用来继承的类(生下来就是当爹的)
抽象类可以添加抽象方法
*/
/* (
function (){
abstract class Animal{
name:string
constructor (name:string){
this.name = name
}
//定义一个抽象方法
//抽象方法使用abstract开头,没有方法体
//抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
//我理解就是给定义好一个方法,具体东西都交给子类去设置
abstract sayHello ():void
}
class Dog extends Animal{
sayHello() {
console.log('wang')
}
}
class cat extends Animal{
sayHello(){
console.log('maio')
}
}
const dog = new Dog('hahha')
}
)()
*/
// //接口就是定了一个规范,对类的限制
// //接口 用来定义一个类的结构(对象的结构)
// //用来定义一个类中应该包含哪些属性和方法
// //同时接口也可以当成类型声明使用
// interface Iface{
// name:string
// age:number
// }
// //借口可以重复声明
// interface Iface{
// gender:string
// }
// const obj : Iface = {
// name:'sss',
// age:18,
// gender:'男'
// }
// /* 接口可以在定义类的时候去限制类的结构
// 接口中的所有的属性都不能有实际的值
// 接口只能定义对象结构,而不考虑实际值(类似抽象类)
// */
// interface Iaa{
// name:string
// sayHi():void
// }
// /*
// 定义类时,可以实现一个接口
// 用类去实现一个接口 implements实现
// 实现接口就是使类满足接口要求(类里面也要有name和sayHi
// */
// class MyClass implements Iaa{
// name: string;
// constructor(name:string){
// this.name = name
// }
// sayHi(){
// console.log('hao')
// }
// }
//属性被任意修改会导致数据不安全
/*
public 修饰的属性可以在任意位置访问(修改)是默认的,任意位置访问
private 私有属性,私有属性只能在类内部进行访问(修改)
通过在类中添加方法使得私有属性被外部被访问
protected 受保护的属性,只能在当前类和当前类的子类使用
*/
// //定义一个类
// class Person{
// private _name:string
// private _age:number
// constructor(name:string,age:number){
// this._name = name
// this._age = age
// }
// // 定义方法,用来获取name属性
// getName(){
// return this._name
// }
// //定义方法,用来设置name属性
// setName(value:string){
// this._name = value
// }
// getAge(){
// return this._age
// }
// setAge(value:number){
// //判断年龄是否合法
// if(value >= 0){
// this._age = value
// }
// }
// //注意:Ts中的getter、setter方法方式
// get name(){
// return this._name
// }
// set name(value:string ){
// this._name = value
// }
// }
// const per = new Person('kk',18)
// //通过set方法修改
// per.setName('猪八戒')
// console.log(per.getName())
// //此时-99就无法赋值
// per.setAge(-99)
// console.log(per)
// /*
// 属性的存储器:
// getter方法获取属性
// setter方法设置属性
// */
// //其实还是调用的set方法
// per.name = '陈平安'
// console.log(per.name)
// //可以将属性定义在构造函数里面
/*
在定义函数或者类时,如果遇到类型不明确就可以使用泛型(泛型就是一个不确定的类型)
*/
//T表示任意类型
function fn<T>(a:T):T{
return a
}
//可以调用具有泛型的函数
let result = fn(10)//不指定泛型,Ts可以自动对类型进行推断
let result2 = fn<string>('hi')//指定泛型
//泛型可以同时指多个
function fn2<T,K>(a:T,b:K):T{
console.log(b)
return a
}
fn2<number,string>(123,'hi')
interface Iq{
length:number
}
//<T extends Iq>表示泛型T必须是 Inter实现类(子类)
function fn3<T extends Iq>(a:T):number{
return a.length
}