复习一下ts的内容顺便记个笔记
ts的数据类型
ts为了使编写的代码跟规范,更有利于维护,增加了类型校验
布尔值boolean :类型为布尔值类型的变量的值只能是true或者false。除此之外,赋值给布尔值的值也可以是一个计算之后结果为布尔值的表达式
字符串 string :字符串类型可以使用单引号和双引号来包裹内容,
数字 number: TypeScript 和 JavaScript 一样,所有数字都是浮点数,所以只有一个 number 类型。
数组 array 在 TypeScript 中有两种定义数组的方式:直接定义: 通过 number[] 的形式来指定这个类型元素均为number类型的数组类型,推荐使用这种写法。数组泛型: 通过 Array 的形式来定义,
元祖 tuple 元组可以看做是数组的扩展,它表示已知元素数量和类型的数组,它特别适合用来实现多值返回。确切的说,就是已知数组中每一个位置上的元素的类型,可以通过元组的索引为元素赋值
枚举 enum 枚举类型 用于标识一些状态或者是一些固定值,可以给一组数值赋予名字,这样对开发者比较友好。枚举类型使用enum来定义
any: any类型的变量会绕过TypeScript的静态类型检测。(失去了类型检查的作用)对于声明为any类型的值,可以对其进行任何操作
never: 永不存在的值的类型。例如:never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。
unknown: 主要用来描述类型并不确定的变量。它看起来和any很像,但是还是有区别的,unknown相对于any更安全。任何类型的值都可以赋给 unknown 类型,但是 unknown 类型的值只能赋给 unknown 本身和 any 类型。
null & undefined: 默认情况下 null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给 number 类型的变量。当你指定了 --strictNullChecks 标记,null 和 undefined 只能赋值给 void 和它们各自。
void: 和 any 相反,any 是表示任意类型,而 void 是表示没有类型,就是什么类型都不是。这在定义函数,并且函数没有返回值时会用到:需要注意:void 类型的变量只能赋值为 undefined 和 null ,其他类型不能赋值给 void类型的变量
ts和js的区别
TypeScript | JavaScript |
---|---|
JavaScript 的超集用于解决大型项目的代码复杂性 | 一种脚本语言,用于创建动态网页 |
可以在编译期间发现并纠正错误 | 作为一种解释型语言,只能在运行时发现错误 |
强类型,支持静态和动态类型 | 弱类型,没有静态类型选项 |
最终被编译成 JavaScript 代码,使浏览器可以理解 | 可以直接在浏览器中使用 |
支持模块、泛型和接口 | 不支持模块,泛型或接口 |
社区的支持仍在增长,而且还不是很大 | 大量的社区支持以及大量文档和解决问题的支持 |
布尔值
// 布尔值类型不允许赋值其他类型
var flag: boolean = true
flag = false
数字类型
var flag: number = 1
flag = 2 // 赋值非number会报错
数组类型 tupel 类型 泛型
// 只允许放入number类型
let arr: number[] = [123, 32323, 1]
// 任意类型都可以放入
var arr7:any[]=[12,234,'']
// 元组类型 tuple 属于数组的一种 必须与元祖类型保持一致
let szh:[string,number,boolean] = ['123',132,true]
// 泛型的方法只能放入 mumber类型 定义只能放入数组 若要放string 只需写 <string>
let arr1: Array<number> = [1, 23, 4, 5, 5]
枚举类型
// 枚举类型 用于标识一些状态或者是一些固定值
enum flags {
kk = 1, bb = 2 }
var f: flags = flags.kk
console.log(f) // 1
// 如果不进行赋值的话打印的是下标
enum Color {
red,
blue,
gg
}
let jj:Color = Color.blue
console.log(jj) // 1
// 如果进行赋值的话打印的是上一个number的加1
enum Color {
red,
blue = 5,
gg
}
let jj:Color = Color.gg
console.log(jj) // 6
任意类型any
var str: any = ''
str = 231321 // 不会报错因为 any可以支持任意类型
// 获取dom元素
var box: any = document.getElementById('#box')
null和undefined类型
// null 和 undefined 是never数据类型的子类型
var num: number
console.log(num) // undefined 正确
// undefined null类型的用处
var num: number | undefined | null
num =99
console.log(num)
void 类型
// ts中的void标识没有任何类型,一般用于定义方法的时候没有返回值
function run():void {
console.log('run')
}
run()
// 返回值必须是一个数字
function run(): number{
return 1 + 9
}
console.log(run())
never类型
// never类型:是其他类型 (包裹null和undefined)的子类型,代表从不会出现的值,只以为着声明never的变量只能被never类型所赋值
var af: undefined
af = undefined
var ab: null
ab = null
var dds: never
dds = 123 // 报错
var sss: never
sss = (() => {
throw new Error('错误')
})()
ts的函数
函数的定义
function run():string {
return '规定的是字符串 必须返回字符串'
}
run()
可选参数
// 匿名函数
var run2 = function ():number {
return 12321231
}
run2()
ts 中定义方法传参
function getInfo(name:string,val:number):string {
return '你好' // 返回必须是一个string
}
getInfo('da', 1)
没有返回值的函数
function sun(): void{
return
}
sun()
方法的可选参数默认参数
// es5 里面的方法的实参和行参是不一样,但是ts中必须有一项,如果不一样就需要配置可选参数
// 可选参数必须配置到参数的最后面
function szh(a:number,b?:string) {
}
szh(1)
// 默认参数 如果想要第一个为可选可不选 那么就要用到默认参数
function hello(a?: number, b: string = '') {
console.log(a)
console.log(b)
}
hello(1)
function szhS(a:number= 321,b?:string) {
}
szhS(1)
函数的剩余参数
function sum(...reset:number[]) :void {
console.log(reset)
}
sum(1, 2, 321, 23, 34, 5, 6, 7, 7, 7, 3)
函数的重载
// java 中方法的重载:重载指的是两个或者两个以上的同名函数,但他们的参数不一样,这是会出现重载的情况
// ts中的重载:通过为同名的一个函数提供多个函数类型定义来试下多种功能的定义
// ts为了兼容es5和es6重载的写法和java是有区别的
// es5 中的出现同名方法下面的方法会替换上面声明的方法
function yellow(name: string): string
function yellow(age: number): string
function yellow(str: any): string {
if (typeof str === 'string') {
return '我叫' + str
} else if (typeof str === 'string'){
return '我的年龄' + str
} else {
return 'aaa' + str
}
}
yellow('小明') // 正确写法
yellow(222)// 正确写法
// yellow(true)// 错误写法
function blue(name: string): string
function blue(name: string, age: number): string
function blue(name: string, age?: number): any{
if (age) {
return '我叫' + name + '年龄' + age
} else {
return '我叫' + name
}
}
console.log(
blue('志豪')
)
console.log(blue('志豪', 22))
// console.log( blue(true)) // 错误写法
箭头函数 es6
setInterval(() => {
},1000)
ts的接口
接口的作用在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,
接口起到一种限制和规范,接口定义了某一批类所需要遵守的规范接口,不关心这些类内部状态数据,
也不关心这些类里方法的实现细节。他规定这你必须提供某些方法,提供这些方法的类就可以满足实际
需要,ts中的接口,类似于Java。同时还增加了更灵活的接口类型,包括属性函数可以和类等
属性接口
传入对象的约束行为和动作的规范
interface FullName {
firstName: string;
seconName: string;
}
function fnh(a:FullName):object {
return a
}
let obj = {
firstName:'321',seconName:'321321'}
fnh(obj) // 只允许传入对象类型 返回的是 object 类型
可选属性 ?
interface back{
a: number,
b?:string // ? 表示参数可选可不选
}
function fns(params:back) {
console.log(params) // {a: 1}
}
fns({
a: 1,
})
ts 加 promise 封装 ajax
// 封装 ajax
interface Config{
type:string,
url:string
data?:string, // ? 表示改 data 是可选可不选
dataType:string
}
function ajax(config: Config) {
return new Promise((reslove,reject) => {
var xhr = new XMLHttpRequest()
xhr.open(config.type,config.url,true)
xhr.send(config.data)
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
if(config.dataType == 'json'){
reslove(JSON.parse(xhr.responseText))
}else{
reslove(xhr.responseText)
}
}
}
})
}
ajax({
type:'get',
url: 'https://api.it120.cc/small4/shop/goods/list',
dataType:'json'
}).then((Res:any) => {
console.log(Res)
})
加密的函数类型接口
// 加密的函数类型接口 对函数传入的返回值和传入的参数进行约束
interface encrypt {
( key:string,value:string):string
}
var md5: encrypt = function (key:string,value:string):string {
return key + value
}
console.log(md5('2', '7')) // 27
可索引的接口
// 可索引接口 对数组的约束 接口定义数组
interface UserArr{
[index:number]:string
}
var TOB: UserArr = ['231', '231123']
console.log(TOB[0]) // 231
对象的约束
interface objType {
[index:string]:string
}
let sun: objType = {
a: 'eq', b: '321' } // 注意 如果换成数组会报错
★ 补充 implements和extends
/*
implements和extends 前者通过声明这个类实现一个或者多个接口,
而后者通过继承父类,拥有了父类的功能,可以重写父类的方法,也可以不重写。相对于implements而言,
它是实现接口,可想而知,实现接口(interface)一般为空的,所以你一般要重写接口所有的方法。
一个类不能extends多个类,但是可以通过接口然后让一个类去implements多个接口
implements与extends的定位
implements
顾名思义,实现,一个新的类,从父类或者接口实现所有的属性和方法,同时可以重写属性和方法,包含一些新的功能
extends
顾名思义,继承,一个新的接口或者类,从父类或者接口继承所有的属性和方法,不可以重写属性,但可以重写方法
注意点
接口不能实现接口或者类,所以实现只能用于类身上,即类可以实现接口或类
接口可以继承接口或类
类不可以继承接口,类只能继承类
可多继承或者多实现
*/
类类型的接口
// 类类型的接口:对类的一个约束 和 抽象类优点相似
interface ClassType {
name: string,
eat(str:string):void
}
class Dog implements ClassType{
name: string;
constructor(name:string) {
this.name = name
}
eat(val:string) {
console.log(this.name + val)
}
}
let huQing = new Dog('我叫')
huQing.eat('周虎请')
class xiaoHua implements ClassType{
public name: string;
constructor(name:string) {
this.name = name
}
eat(val:string) {
console.log(this.name + val)
}
}
let xiaoHuas = new Dog('我是假的')
xiaoHuas.eat('自己')
接口的扩展
/// 接口的扩展 可以实现接口继承接口 继承的是 ClassType
interface ZHQ {
eat():void
}
// 继承接口
interface ClassType extends ZHQ {
moz():void
}
class Webs implements ClassType {
// ClassType 相当于有两个方法
public name: string;
constructor(name: string) {
this.name = name
}
eat() {
console.log(this.name)
}
moz() {
console.log(this.name + ' 我是第二个')
}
}
var w = new Webs('大老鼠')
w.eat() // 我叫周虎请
w.moz() // 我是假的自己
接口的练习
/*
接口 :在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范
泛行通俗理解,泛型就是解决类,接口方法的复用性。
*/
interface obj2 {
yh: string,
vg: number,
bj: [string, number]
}
interface obj1 {
hx: number,
hk: string,
obj: obj2,
vb: [string, number ]
}
let obj = {
hx: 22132,
hk: '31321',
obj: {
yh: '31321',
vg: 31321321,
bj: ['3212', 645364,]
},
vb:['2',5]
}
console.log(obj)
泛型
泛型 软件工程中,我们不仅要创建一致的定义良好API。同时也要考虑可重用性,
组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,正在创建大型系统时,为你提供了十分灵活的功能。
再向c# 和 java这样的语言中可以使用唤醒来创建可重用的组件,一个组件可支持多种类型的数据。这样用户就可以自己的数据类型来使用组件
通俗理解就是解决,类,接口,方法的复用性,以及对不特定的数据类型的支持。
泛型:泛型可以帮助我们避免重复的代码以及对不特定的数据类型的支持(类型校验),
泛型的定义
// 只能返回sting 类型的数据
function fn(a:string):string {
return a
}
fn('321312')
// 同时返回 string 和 number 类型
function fn1(a:string):number | string {
return 1
}
fn1('231')
// any 可以解决但是放弃了类型检查
function fn2(a:string):any {
return 1
}
fn2('231')
泛型函数
// 比如说我传入的什么类型就返回什么类型 传了 数字 返回数字 传了字符串返回字符串
// T 表示泛型,具体是什么类型,在调用方法的时候决定
function eq<T>(value:T):T {
return value
}
eq<number>(1)
eq<string>('2321')
// 返回的时候什么类型都可以
function eqs<T>(value:T):any {
return 4423
}
eqs<number>(1)
eqs<string>('2321')
泛型类
// 比如说有个最小的堆算法,需要同时支持string number 通过类和泛型来实现
class typeSort<T> {
public name: T[] = []
add(val:T):void {
this.name.push(val)
}
min() {
// 拿到第一项
let item = this.name[0]
for (let i = 0; i < this.name.length; i++) {
if (item > this.name[i]) {
item =this.name[i]
}
}
return item
}
}
let sortTypes = new typeSort<number>()
sortTypes.add(-1)
sortTypes.add(5)
sortTypes.add(6)
console.log(sortTypes.min()) // -1
let sortTypes1 = new typeSort<string>()
sortTypes1.add('d')
sortTypes1.add('c')
sortTypes1.add('b')
console.log(sortTypes1.min()) // b
函数类型接口
interface workType {
(key:string,val:number):string
}
const fnss:workType = function work(key:string,val:number):string {
return key + val
}
fnss('213', 21)
泛型接口
interface ky {
<T>(key:T,val:T):T
}
const worke:ky = function<T>(key:T,val:T):T {
return key
}
worke<string>('321', '23')
// 第二种
interface Cofig<T> {
(value:T):T
}
function getData<T>(value: T): T{
return value
}
var myGet: Cofig<string> = getData
myGet('e2qe')
// myGet(234) 报错
ts里的类
// es5 中的类
function fn(name:string,age:number) {
this.name = name
this.age = age
}
let arr = new Fn('',1)
创建一个类
class Person {
name: string // 前面省略了 public 关键词
constructor(n:string) {
// 构造函数 实例化类的时候触发的方法
this.name = n
}
run():void {
alert(this.name)
}
}
var p = new Person('孙志豪')
p.run()
// 在类里面进行调用
// 在函数类里面进行传值
class Person {
name: string
constructor(name:string) {
this.name = name
}
run(): string{
return this.name
}
setName(name: string):void {
this.name = name
}
}
var p = new Person('孙志豪')
console.log(p.run()) // 在类里面进行调用
p.setName('你好') // 在函数类里面进行传值
在 ts中实现继承 extends 、super
class Person {
name: string
constructor(name: string) {
this.name = name
}
run(): string {
return `666666${
this.name}在运动`
}
}
// var p = new Person('孙志豪')
// console.log(p.run())
class Web extends Person {
constructor(name: string) {
super(name)
}
}
const w = new Web('孙志豪')
console.log(w.name)
console.log(w.run()) // 运行
类里面的修饰符public,protected,private
/*
类里面的修饰符 typeScript里面定义属性的时候为我们的提供了三种修饰符
public :公有 在类里面、子类、类外面都可以访问
protected:保护类型 在类里面、在子类里面都可以访问、在类外部没法访问
private:私有 在类里面可以访问子类,类外部都没法访问
属性如果不加修饰符 默认就是 公有的属性 public
*/
public:类外部访问的公有属性
// public :公有 在类里面、子类、类外面都可以访问
class Father {
public name: string // 不写public也可以 前面省略了 public 关键词
constructor(name: string) {
this.name = name
}
run(): string {
return `${this.name}在运动`
}
}
const p = new Father('哈哈')
console.log(p.name)
protected:保护类型
// protected:保护类型 在类里面、在子类里面都可以访问、在类外部没法访问
class Father2 {
protected name: string
constructor(name: string) {
this.name = name
}
run(): string {
return `${
this.name}在运动`
}
}
const p2 = new Father2('哈哈')
// console.log(p2.name) // 无法访问
console.log(p2.run()) // 可已访问
private:私有
// private:私有 在类里面可以访问子类,类外部都没法访问
class Father3 {
private name:string // private 在当前类是可以访问的
constructor(name:string) {
this.name = name
}
run ():string{
return `${
this.name}在运动`
}
}
class Webs extends Father3 {
constructor(name: string) {
super(name)
}
work() {
console.log(this.name) // 这里会爆红因为this.name 是私有的只能在Father3里面使用
}
}
命名空间
/*
命名空间
在代码量较大的情况下,为了避免各种变量命名冲突,可以将相似功能的函数,类,接口等放置到秘密空间内。
命名空间和模块的区别。
命名空间:内部模块,主要用于组织代码。避免命名冲突
模块:ts的外部模块的简称,侧重代码的复用,一个模块里面可以有多个命名空间
*/
namespace A{
interface Animal {
name: string,
eat():void
}
export class Dog implements Animal{
name: string;
constructor(theName: string) {
this.name = theName
}
eat(): void {
console.log(this.name+ '666')
}
}
export class Cat implements Animal {
name: string;
constructor(theName: string) {
this.name = theName
}
eat(): void {
console.log(this.name + '7777')
}
}
}
var szh = new A.Dog('打狗')
szh.eat()// 使用
namespace B{
// 内部数据不会受外部影响
interface Animal {
name: string,
eat():void
}
export class Dog implements Animal{
name: string;
constructor(theName: string) {
this.name = theName
}
eat(): void {
console.log(this.name+ '666')
}
}
export class Cat implements Animal {
name: string;
constructor(theName: string) {
this.name = theName
}
eat(): void {
console.log(this.name + '7777')
}
}
}
后续还会更新…