TypeScript的数据结构 03
前言TS 是 JS 的一个超集保留JS原有语法和动态特性的基础上添加可选静态类型和基于类的面向对象编程。1. JS的面向对象编程JavaScript 是基于函数实现面向对象编程的。JS的设计者在最初就选择了和当时主流语言JAVA / C 等“基于类的模型”不同的技术路线—— “基于原型的面向对象”让对象直接从其他对象中继承而不需要抽象出“类”作为中介。1.1 面向对象实现1. JS 创建构造函数函数拥有一个prototype属性JS引擎内部进行的初始化动作prototype 属性会指向另一个对象 Person.prototype.publicFun构造函数角度构造函数 的 公共仓库Prototype 中的资源publicFun实例对象角度实例对象的原型prototype的对象隐式父对象2. 通过 new 创建实例创建一个新的空对象该实例对象的内部指针__proto__执行构造函数的prototype对象执行构造函数并将函数体的this绑定到这个新的对象中返回上述新创建的对象prototype用于存放实例 公共行为资源 的仓库减少内存浪费// Person.prototype.PublicFun function(){} var Person new Function() Person.prototype { construct: Person; publicFun: function(){console.log(自定义公共行为)} }原始数据结构的原型属性列举StringlengthslicesplittrimindexOfreplaceArraylengthpushpopmapfilterforEach内部封装迭代器concatES6Map: size, set(key, value), get(key), has(key), delete(key), clear(), keys(), values(), entries()Set: add(value)2. TS 的核心机制/规则可选静态类型 和 基于类的面向对象编程可选静态类型 编译阶段对变量的类型进行检查可以通过定义类型判断也可以通过赋值自动推导弥补JS动态类型在复杂协作和项目上造成的负担。为什么理论上TS定义参数要添加类型但是实际可不写已赋值/ 可写初始化 或 类型为any值得一提 TS 的核心优势之一 “类型推断”。那么“类型推断”的核心价值1. 优化 JS 这种动态类型语言中参数类型在开发中可任意改变的灵活性在复杂开发中易产生参数错乱的情况从而对参数类型严格监控。2. 简化 TS 代码的编写提升代码的可读性与维护性。注意编译时进行类型推断如果从接口获取了不合规的数据TS 的推断无法在浏览器运行时帮助拦截报错的需要配合运行时的校验库如 Zod 等TypeScript严格模式strict mode配置strict: true或者单独开启noImplicitAny: true基于类的面向对象编程 对比JS的动态类型且在运行时可以给原型添加属性的特点类的语法明确定义了属性、方法、访问权限等所以TS编译器分析阶段 根据类固定的结构提取出类型信息配合可选静态类型进行严格检查检查通过后编译为JS的function才能在浏览器中运行。3. TS基础数据结构类型的声明、类型的集合3.1. 基础类型boolean string number array null undefinedlet flag: boolean true let course: string caorui let grade: number 98 // undefined 和 null 只能赋值给自己或者any let u: undefined undefined let friend: null null let classArr: string[] [basic,execute] let classArr1: Arraystring [basic,execute]tuple 元组tuple 有限个数和有限类型type 无限集enum 枚举默认是数据类型枚举从零开始依次递增声明变量 any unknow声明函数的返回值 void nerver3.2. 复合类型将多个值组合成一个复杂的结构。3.2.1. 对象类型的对比object Object {}1object 引入非原始类型对象自己携带了属性通用对象的属性如 .hasOwnProperty / .toString / .valueOf类型检查通过如果遇到自定义的业务属性TS 会因为不认识将这些属性禁用所以此时就需要用到 type/interface创建类型别名使得业务属性通过TS的类型检查// 包含普通对象{}, 数组函数类实例…… let obj: object; obj { name: Alice }; obj [1, 2, 3];2Object 原始类型 非原始类型继承 JavaScript 中对象构造函数 以及原型链 的类型3{} 能接受原始类型但是不能访问属性。// 联合类型的限制作用{} 限制 value 不能是 null 或 undefined function valueDataT extends {}(value: T) { console.log(value); }3.2.2 核心类型系统interface 和 type 的理解3.2.2.1. interface实际意义核心定位定义抽象接口将核心业务逻辑和外部依赖细节隔离即业务做什么和怎么实现分离。符合“依赖倒置原则Dependence Inversion Principle”// 编译阶段只做结构校验 interface IStorage{} // 强制类实现接口定义的结构 class LocalStorage implements IStorage{}持久化存储解耦为例// “单例模式” “类型导出”模式 export type SessionToken { accessToken: string, refreshToken: string, expires: number, } // 对外暴露相同的方法和属性 export interface StorageLike{ setItem(key: string, value: string): void getItem(key: string): string | null removeItem(key: string): void } // 业务逻辑依据interface契约操作 export class TokenStore{ private storage:StorageLike constructor(storage:StorageLike){ this.storage storage } } function anotherStorage:StorageLike{} const definedStore typeof window ! undefined window.localStorage ? window.localStorage : anotherStorage export const tokenStore new TokenStore(definedStore)思考1. 对比使用 type 和 interface 定义对象类型的差异2. 解耦思想实际应用场景持久化存储网络场景时间处理等3. 内置数据结构类型有哪些TS 继承 JS 的内置对象并添加了强类型支持。比如TS 给 JS 的 Set 和 Map 增加了泛型支持Set集合ES6存储唯一值去重Map映射ES6存储键值对键值可以是任何类型TS的内置工具类型Pick、Record、Partial、Omit 等。自定义高级数据结构有哪些结合 接口 泛型 实现复杂的业务数据结构// 定义通用数据结构接口契约 interface PageResT{ list: T[], total:number}5. 内置的工具类型Pick: 从一个已有类型里挑出指定的几个字段/属性组成一个新的类型。// Storage —— Web Storage API type StorageType PickStorage, getItem|setItem|removeItem6. 类型的计算通过基础类型计算出复杂的数据结构联合类型相当于“或”运算允许数据有多种形态。交叉类型相当于“与”运算将多个结构合并为一个。存在一些变量是多种不同类型的合比如象棋的颜色/身份所以需要对多种类型进行合并—— 联合类型联合类型的存在让TS编译器在运行到某一行代码时无法确认变量的类型是 —— 引申出类型守卫ininstanceoftypeof需要对变量类型进行判断保证多种类型中选择了合适的一个。类型守卫和断言配合使用。类型守卫针对不确定的情况增加一层判断保障断言针对对系统非常熟悉的情况强行明确变量的类型as!()尖括号减少其他繁琐操作。它们结合使用确保TS编译阶段的类型检查工作。7. 类型进行动态化泛型 接收 类型参数像函数传变量值一样动态操作变量类型并返回具体的数据结构。函数存在形参和实参JavaScript中的实参只有在函数真正运行时才会知道实际参数而JS的形参 fn(10) 是无类型的所以经常写 typeof 进行检查。而 TypeScript 的 泛型针对JS中存在的问题进行了完善。泛型 通过 显式传递 / 隐式传递 将 形参的类型传递进来使得函数在运行前就已经知道参数的类型。function startClassT,U(name:T, score:U): T{ return name score } startClassstring,number(ts,5)思考TS的语法糖装饰器Java中的注解