大家好,欢迎来到IT知识分享网。
Typescript学习笔记
什么是Typescript
TypeScript是一种由微软开发的开源、跨平台的编程语言。它是JavaScript的超集,最终会被编译为JavaScript代码;TypeScript适合用来编写基于node的大型应用;ts的静态语言特性,能帮助我们在开发时候就发现自己语法的错误,而非像其他js在运行时才发现;ts的类型定义,让代码更加规范,在调用一些方法和api时,能准确的得到方法参数和返回值提示,减少了以往js需要api文档才能开发的问题;
Typescript 的数据类型
基本数据类型
布尔类型(boolean); 数字类型(number); 字符串类型(string); 数组类型(array); 元组类型(tuple); 枚举类型(enum); 任意值类型(any); null和undefined; void类型; never类型;
常用类型(与java的定义差不多)
//最常用的类型 let bool:boolean = true; let str : String = "字符串"; let num : number = 1.2; //两种数组的定义方式 let strArr : string[] = ["1","23","123"]; let numArr : Array<Number> = [1,2,3];
Typescript 的强类型判断非常严格,当试图为上文的 str赋值 数字类型时,会报错,体现了ts的静态语言特性,强类型判断
//元组(Tuple)可以理解为一个长度,每一项元素类型都确定的数组 let peopleArr: [string, string, number] = ['Dylan', 'male', 23] //数组中元素的类型和长度都是固定的,与定义的类型和长度一样 //混合类型的数组 let arr:(number|string)[] = [12,'aa','a'];//定义数组类型时,使用 | 连接(union type联合类型),这数据可放入多种类型
any类型及其与object的区别
any任意值类型,在强调类型的ts中,ts对象可以让被赋予如何类型,也可以从any中去任意属性和方法(即使不存在的属性和方法)
let testObj : any = {
}; testObj=1; testObj="aaa"; testObj={
sayHi(){
console.log("sayHi") } } console.log(`testObj不存在的属性---${
testObj.aa}`)//调用不存在的属性aa,编译不报错,运行也不保存 console.log(`调用不存在的方法开始`) testObj.sayNo();//不存在的方法 console.log(`调用不存在的方法结束`) testObj.sayHi();
如上代码和运行结果可以看到,any修饰的变量,可以接受任意类型,可以调用不存在的属性,但是不能调用不存在的方法;如上,调用不存在的方法,编译不报错,但是运行到 “调用不存在的方法开始`”这个log后,程序开始循环无法正常的往下走;any 类似原生的js对象,ts放弃对此类修饰对象的类型判断;
any与object的区别,虽然在接受参数上两者都能接收不同类型,但是编译器,object 使用不存在的属性和方法时,object类型编译报错
any可以以赋值给任意类型(never类型除外),object则不能赋值给任意类型;any对象可以赋值给string,但是object不行
never any unkown
将三种类型一起讲,是因为 any和unkown顶部类型,never是底端集合
any和unkown 是一切类型的超级类型(supertype)任何值都能冠以类型any和unkown
never是一个空集合,任何值都不能冠以类型 never;将某个值的类型解析为 never,编辑就会报错;空集合可包含于任何非空集合,因此never 是一切其它非空类型的子集合。这就是为什么 never 被称为底端集合。
包装类型
interface
以IEMP-SXTL-BFF项目代码来演示interface功能
//在src\inits\modelData\index.ts 向外暴露的CommonResultData / * 服务返回数据通用结构 */ export interface CommonResultData {
code: number; msg: string; data: Record<string, any>[] | null; } let data :CommonResultData = {
code:1, msg:"aaa" } //这种定义,要求该类型的实例的对象,必须要有 code msg data属性,以code为列,code可以 = 数字,null,underfined,但是不能没有code属性 //如果偏偏要让 code 可有可无,则可以 code?: number; 使用问号,则属性中没有code,编译也不会报错
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UNusM0NH-17)(C:\Users\tttare\AppData\Roaming\Typora\typora-user-images\image-.png)]
interface无法用new 实例化,class可以
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IrDWkKha-18)(./img\2020-12-31_.png)]
如上图,我们在使用interface修饰的类型时,能很清晰的看到这个类型所需要的属性,这也是ts相比传统js的优势,能让我们在没有api文档的情况下,知道使用的类型中的属性,属性类型,方法,方法参数等信息,这也是ts解决的痛点之一;
let comdata : CommonResultData = {
code:1001, msg:"aass", data:null };//给CommonResultData类型赋值时,CommonResultData类型的三个属性,必须全都要定义,不能是underfine,类型也不能不同
interface和java的接口还是很像的,interface能继承interface,interface不能有方法体,不能用private修饰方法
ts建议给interface的方法确定返回值
class
在IEMP-SXTL-BFF项目中,class修饰的类型承担更大的作用;class中有大量的方法和注解,主要用来编写业务逻辑
//定义一个oprate类 class Oprate{
public sayHi(){
console.log('public say hi') } private sayHello(){
console.log('private say hello') } public static sayHalo(){
console.log('static say halo') } }
由上图可知,class的实例能使用被public修改的方法,不能使用被private或static修饰的方法;static修改的方法,直接用类型调用
private 和 public都与java的类似,只是static修饰的方法,类的实例不能使用,与java不相同
extends ,implements,多态
interface不能被class继承
interface能继承interface,interface不能有private修饰方法,不能有方法体;
class实现interface必须也定义interface属性,实现interface的方法
class继承class,能使用父class的方法及属性
ts也有多态,interface接收实现类的实例,class接收子类的实例
union(并集) 和 intersection(交集)
定义几个class对象 用来测试交集和并集
interface OpInterface {
data:number; sayToday():number; } class Oprate implements OpInterface{
data:number; public sayToday():number{
return 12; } } class OprateSon extends Oprate{
public saySon(){
console.log("son class") } } class Dev {
code:number; data:number; public saySon(){
console.log("son class") } public sayDev(){
console.log("dev class") } } class Mix {
code:number; //下面的方法和属性在 生成的并集中也不存在,但是new Mix可以赋值给并集type t1 : string='str'; sayNo(){
} } class And {
data : number; public saySon(){
console.log("son class") } }
并集,ts以 | 符号表示
//基本数据类型并集 type mixBasic = number|String; let a2 : mixBasic = 1; let a3 : mixBasic = 'str'; //包装类型并集 type mix = Dev | OprateSon; let devObj : mix = new Dev(); let opObj : mix = new OprateSon();
交集,ts以 & 符号表示
//基本数据类型 //mixBasic = number|String;她与string的交集 便是string type andBasic = mixBasic&string; let and1 : andBasic = "aaa"; //包装类型并集 type mixOne = Dev | OprateSon; type mixTwo = Dev | Oprate; type and = mixOne & mixTwo; let obj1 : and = new Dev(); let obj2 : and = new OprateSon();//mixOne 和 mixTwo 的交集应该只有 Dev类型,为啥可以赋值 OprateSon //因为 OprateSon 继承了 Oprate,所以ts继承的特性也体现出来了 OprateSon&Oprate 产生的交集是 OprateSon
枚举
枚举定义方式
enum OprateEnum{
START,END } console.log("start..."+OprateEnum.START) console.log("end..."+OprateEnum.END)
运行结果
可以看出,ts的枚举和java枚举有很大不同,在我们没有给START,END赋值的情况下,枚举类型默认从0 开始自增赋值
enum OprateEnumTwo{
START,SECOND=3,THREE,END } //将中间值 设为3 看ts为其他值赋值多少 console.log("start..."+OprateEnumTwo.START) console.log("second..."+OprateEnumTwo.SECOND) console.log("three..."+OprateEnumTwo.THREE) console.log("end..."+OprateEnumTwo.END)
运行结果
可以发现,还是从0开始,但是 因为我们给SECOND赋值了3,SECOND以后的枚举值,以她为起点自增
枚举类属性不能用数字命名
与上面的数字值枚举不同,如果你给枚举赋值了字符串,那该枚举属性之后的属性,必须赋值
当我们去掉T3 T4时,查看运行结果
TS的枚举类型,要特别主要自动赋值,自增这个特点
注解
TS提供的高级工具类
- type : 用来接收ts的类型,可以接收一个新的类型,也可以其他ts类型建立别名,别名不会新建一个类型,而是创建一个新名字来引用此类型(一个别名能对应多种类型),type 就是用来接收TS类型的
//代码中临时创建一个新的类型,用type对象接受 //NewType 是代码中临时定义的对象 type NewType = {
code?:number, name?:string }; let typeObj : NewType = {
code:12, name:"sdad" }; //为已有类型创建别名 //NewCommonResultData是CommonResultData别名,实际作用和CommonResultData一样 type NewCommonResultData = CommonResultData; let newData : NewCommonResultData = {
code:10, msg:"aass", data:null }; // type接收联合类型,对应多种类型 type DataOrStr = string | CommonResultData; let dataOrStr : DataOrStr = "aaa"; dataOrStr = {
code:10, msg:"aass", data:null };
- Partial : 产生新的类型给T所有属性加上?,变为可选
type stu = {
readonly name:string,//只读,定义后此属性不能修改 sex:string,//属性 ? 代表是否可为underfined,不要? 则接受值时,必须全部使用 level:number }; let stuObj : stu = {
name:"武汉",sex:"女",level:7}; //newStr 和 stu 互不影响,newStr时基于stu新的类型 type newStr = Partial<stu>;//Partial 产生新的类型给所有属性加上?,变为可选 let student : newStr = {
level:1};//编译不报错,name和sex都可以不定义
- Required : Required 与Partial正好相反,使得所有属性,必须定义
- Readonly : 给T所有属性都加上readonly 属性,使其定义后无法修改
type readOnlyStu = Readonly<newStr>; let readOnlyS : readOnlyStu = {
name:"不可能变更"}; //readOnlyS.name = "aaa";//ReadOnly产生的type不能被修改 //readOnlyS.level = 2;//所有属性都不能被修改
- Pick<T,K extends keyof T> : 从T中挑选部分属性生成新的type
type halfStu = Pick<stu,"sex"|"level">;//Pick 从stu中,拿出部分属性,产生一个新的type let halfStuObj : halfStu = {
sex:"nan",level:1};
- Omit<T,K extends keyof T>: 删除T部分属性,产生一个新的type,与Pick正好相反
type delStu = Omit<stu,"sex">;//Omit 删除部分属性,产生一个新的type,与Pick正好相反 //let delStuObj : delStu = {sex:"a"};//sex被删除,编译报错
- Extract<T, U>:作用是从 T 中提取出 U
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a" type T1 = Extract<string | number | (() => void), Function>; // () => void
- Exclude<T, U>:将 T 中某些属于 U 的类型移除掉。
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c" type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c" type T2 = Exclude<string | number | (() => void), Function>; // string | number
- Record<T,K extends keyof T>
Record使用效果如下
type petsGroup = 'dog' | 'cat' | 'fish'; interface IPetInfo {
name:string, age:number, } type pet = Record<petsGroup,IPetInfo>; let petObj : pet = {
dog : {
name:'dog', age:5 }, cat : {
name:'cat', age:9 }, fish : {
name:'fish', age:2 } }
IEMP-SXTL-BFF项目代码解析
项目启动环境
- 安装nodejs
- 更新配置npm
- 项目部分依赖需要python和c++类库,安装python,vs_community安装c++桌面开发工具
- npm run dev 启动项目开发环境应用
Koa基于nodeJs的Web框架
服务启动入口
src\index.ts 是整个服务器程序的启动入口
const app = await appInit.init();//调用src\app.ts的init方法,主要返回Koa实例 // 获取Koaservice运行端口号 const serverPort = normalizePort(String(commonCfg.bffConfig.port) || '3000');//端口配置于src\config //nodeJs创建一个服务器的代码 const server = http.createServer(app.callback()); //事件掩饰设置 0 立即执行 server.setTimeout(0); //绑定服务器端口 server.listen(serverPort); server.on('error', onError); server.on('listening', onListening);
koa app设置
export default {
async init(): Promise<Koa> {
//定义一个Koa 服务端实例 const app = new Koa(); // 全局变量初始化 globInit(); // 全局错误信息处理 app.use(globalError); // 全局token校验 // app.use(checkToken(AuthService.checkToken)); // spring监控 app.use(actuator()); // 重放攻击保护 // if (commonCfg.env !== 'dev') {
// app.use(replayAttack(['swagger', 'actuator', '/system', 'example'])); // } // 日志 app.use(koaLogger()); // 请求信息打印 app.use(requestInfo); // 数据压缩 app.use( koaCompress({
threshold: 2048, flush: require('zlib').constants.Z_SYNC_FLUSH, }), ); // 格式化返回值 app.use(resFormatter); // 初始化框架 initFrame( app, {
}, {
authorizationChecker, }, ); // eureka注册 if (commonCfg.registerToEureka) {
eureka.start(async () => {
await initData.init(); }); } else {
await initData.init(); } return app; }, };
主要定义了 服务器端实例
const app = new Koa();
app.use(参数:方法):只能用于注册中间件并且必须是生成器函数
app.use(function)
路由设置
src\inits\initFrame.ts中定义了koa-router及其配置,及外部访问程序的设置
const defaultRoutingControllersOptions: RoutingControllersOptions = {
//controller层包路径,于javacontroller的逻辑一致 controllers: [`${
baseDir}/controllers//*{.js,.ts}`], //middlewares包路劲,配置了koa-actuator 应该是永濑监控程序运行情况的 middlewares: [`${
baseDir}/middlewares//*{.js,.ts}`], //url前缀 routePrefix: '/bff/v1', validation: true, cors: true, defaultErrorHandler: false, }; // koa app设置路由规则 koa.use(router.routes());
编写对外提供的服务(controller + service)
如上,我们定义了一个web服务器的实例,端口,url前缀,接下来编写程序,为服务提供功能
在controllers包下定义controller类:TttareController
/ * @Description: * @author: 测试ts编写的controller层 * @date: 2020/01/02 */ import {
Inject } from 'typedi'; import {
Body, Get, JsonController, Param, Post, Put, Authorized, Ctx } from 'routing-controllers'; import {
ApiOperation, ApiTag } from '../lib/routing-controllers-openapi'; import CreateUserBody from '../definitions/CreateUserBody'; import {
CustomError } from '../common/CustomError'; import UserDataManager from '../biz/example/UserDataManager'; @ApiTag('示例') @JsonController('/tttare') export default class TttareController {
@Inject() private userDataInstance: UserDataManager;//ts注入 @ApiOperation('测试controller的路由和注入', '测试') @Get('/noParam') getTestData() {
return this.userDataInstance.getTestData(); } @Get('/getById/:id')//rest风格 url传参 getOne(@Param('id') id: number) {
return {
name: `User #${
id}` }; } //http://localhost:3001/bff/v1/tttare/getById/12 //请求返回 //{
// "name": "User #12" //} @ApiOperation('测试controller的路由和注入,调用参数有返回值', '测试') @Post('/param') getTestDataWithParam(@Ctx() ctx,//ctx是context的缩写 @Body() queryParam: any) {
console.log(ctx); console.log(queryParam); return this.userDataInstance.getTestDataWithParam(queryParamList); } }
@Ctx() ctx是context的缩写中文一般叫成上下文,这个在所有语言里都有的名词,可以理解为上(request)下(response)沟通的环境,所以koa中把他们两都封装进了ctx对象,koa官方文档里的解释是为了调用方便,ctx.req=ctx.request,ctx.res=ctx.response,类似linux系统中的软连接?最终执行还是request和response对象
// log ctx对象如下 {
request: {
method: 'POST', url: '/bff/v1/tttare/param', header: {
'content-type': 'application/json', 'user-agent': 'PostmanRuntime/7.24.0', accept: '*/*', 'cache-control': 'no-cache', 'postman-token': 'aecaa0bc-108c-4a4e-8535-d36304b21b61', host: 'localhost:3001', 'accept-encoding': 'gzip, deflate, br', connection: 'keep-alive', 'content-length': '35' } }, response: {
status: 404, message: 'Not Found', header: {
vary: 'Accept-Encoding, Origin' } }, app: {
subdomainOffset: 2, proxy: false, env: 'dev' }, originalUrl: '/bff/v1/tttare/param', req: '<original node req>', res: '<original node res>', socket: '<original node socket>' }
@Body() queryParam: any body是请求体,接收请求的json字符串,将json字符串转为js对象
//log queryParam对象如下 [ {
'name ': 'tttare', sex: '男', level: 2 }, {
'name ': 'tom', sex: '男', level: 3 }, {
'name ': 'mick', sex: '男', level: 2 }, {
'name ': 'nancy', sex: '女', level: 2 } ]
项目使用typedi框架实现依赖注入
//controller层引入 Inject依赖注入service import {
Inject } from 'typedi'; @Inject() private userDataInstance: UserDataManager;//ts注入 // //service使用 Service做控制反转,将UserDataManager实例的产生交个框架 import {
Service } from 'typedi'; @Service() export default class UserDataManager
编写service,注入controller层调用
src\biz\example\UserDataManager.ts的ts编写逻辑处理
//给学生对象按年级 level 分类 public getTestDataWithParam(queryParamList: any[]):Map<number,any[]>{
//ts提供的Map type,和java一样,key-value存储 let map = new Map<number,any[]>(); //利用map的api进行学生分组 queryParamList.forEach(item=>{
if(map.has(item.level)){
map.get(item.level).push(item) }else{
map.set(item.level,[item]); } }) return map; }
测试编写的接口
断点调试
在vscode界面找到debugger窗口,点击驱动项目
debugger项目启动端口和dev端口一致,要先关了dev环境
debugger启动配置
debugger过程
开发常见API解析-进阶
异步相关(async await Promise)
异步操作一般是在主线程中,开辟新的线程去做耗时操作,项目中最多的便是网络请求;
- async 修饰方法,代表此方法方法体内有异步操作,且改方法的返回值会被包装成一个Promise ,默认将方法的返回值作Promise中 resolve方法的参数
- await 只能存在与被async修饰的方法体内,来修饰一个异步调用操作(或者说修饰一个返回Promise的方法),用来暂停主线程,等待异步调用完成,主线程才开始往下走,感觉是将原先的异步操作,变为了同步一的一种效果,一般是因为主线程下面的操作需要异步调用(网络请求)的返回值;(await 所取的参数来自于Promise中resolve函数的赋值,也就是请求成功时Promise调用的resolve方法)
- Promise 是为异步编程提供了一种解决方案
名称:Promise,译为“承诺”,这也就表达了将来会执行的操作,代表异步操作; 状态:一共有三种状态,分别为pending(进行中)、fulfilled(已成功)和rejected(已失败)。 特点:(1)只有异步操作可以决定当前处于的状态,并且任何其他操作无法改变这个状态; (2)一旦状态改变,就不会在变。状态改变的过程只可能是:从pending变为fulfilled和从pending变为rejected。如果状态发生上述变化后,此时状态就不会在改变了,这时就称为resolved(已定型)
Promise使用实例
public static testMethod(){
//Promise 如何实现异步操作 //将异步操作包装入Promise对象的 (resolve, reject) => {}方法中 const promise = new Promise((resolve, reject) => {
let error = '连接失败'; let value ="请求成功"; let success = false; if (success) {
resolve(value); //pending => fulfilled } else {
reject(error); // pending => rejected } }); //如何获取异步操作的执行结果 promise.then((v)=>{
//then 获取到 resolve(value) 方法的参数 value console.log(`then:${
v}`) }).catch((e)=>{
//catch 获取 reject(error) 方法的参数 error console.log(`catch:${
e}`) }).finally(()=>{
//finally 必须执行的处理 console.log("处理结束") }) return promise } //调用testMethod方法 @post("/forTest") async fotTest(ctx){
console.log("start...") AccountService.testMethod(); console.log("end...") }
执行结果
如上图所示,Promise对象已经将我们的操作变为异步操作了
async 标记方法实例
//方法和简单,async能不能让方法异步 public static async testMethod2(){
console.log("async方法执行中") return "aaa" } @post("/forTest") async fotTest(ctx){
console.log("start...") //async 的返回值只能用Promise对象接收 let p:Promise<any> = AccountService.testMethod2(); p.then((v)=>{
//then中操作方法的返回值 console.log("取到asyn方法返回值"+v) }) console.log("end...") }
如上图所示,async标记的方法,方法体并不是异步的,异步操作需要Promise来实现,new Promise和Promise的then,catch,finally是异步的;故async更多是标记方法存在异步操作,并使得方法的返回值被Promise包装
IBS-BFF项目异步操作实例(async await Promise的组合运用)
//RedisUtil中的hgetall方法,讲操作redis异步进行 async hgetall(key): Promise<any> {
return new Promise((resolve, reject) => {
client.hgetall(key, (err, res) => {
//成功与失败都调用resolve,是为了方便用 await取值 if (err) {
resolve(false); } else {
resolve(res); } }); }); } //await 修饰的async方法,会直接拿到方法返回值中的 resolve参数 //await redisUtil.hgetall 可知,data为Promise resolve方法的参数,及默认取调用成功的返回值 const data = await redisUtil.hgetall(this.inSettleAccountKey); if (data !== false) {
for (const key in data as any) {
if (data.hasOwnProperty(key)) {
if (new Date().getTime() - parseFloat(data[key]) >= this.expiredTime) {
await this.deleteAccountCalData(parseInt(key), true); } } } } else {
G.logger.error('账户缓存数据读取出错'); } //await Promise.all参数是一个异步方法集合,dataList则为一个数据, //长度为方法集合长度,dataList的集合对应的是每个异步方法的返回值 //all将多个异步操作放在一起成为一个新的Promise,如果都成功,则返回长度相同的返回值数组 //一旦有一个失败,则返回第一个失败操作的reject状态值, //有点事务的意思,集合内的异步方法要么都成功,只要有一个失败,则认为他们都失败 const dataList = await Promise.all([ MeterInfoQuery.queryLineShareSchemeAccountMapData(), this.queryLineGatewayMapData(lineIDList), MeterInfoQuery.queryLineAccountDataMap(lineIDList), ]);
装饰器和注解
装饰器(Decorator):仅提供定义劫持,能够对类及其方法、方法入参、属性的定义并没有提供任何附加元数据的功能。
注解(Annotation):仅提供附加元数据支持,并不能实现任何操作。需要另外的 Scanner 根据元数据执行相应操作。
TS中,注解和装饰器是可以说是一个东西,缺一不可,注解提供元数据,即其可以通过修饰类和方法、参数上,为装饰器提供元数据(类信息,方法信息,参数,以及注解本身的入参),而装饰器则负责实现对元数据 进行功能的扩展;
@controller('/account') export default class AccountController extends BaseController {
~ ~ ~ ~ ~ ~ ~ ~ }
以TS Web服务开发常用的@controller注解为例子,其定义如下
export declare const controller: (path?: string) => ClassDecorator;
注解将自身的参数 path传递给了ClassDecorator 类装饰器,而类处理器本身是一个Function
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
typedi框架的AOP和IOC
@Service() export default class UserDataManager {
~~~~~~ } @JsonController('/users') export default class UsersController {
@Inject() private userDataInstance: UserDataManager; }
//TODO
常用工具类
- moment 时间日期操作工具类
import * as moment from 'moment'; const startTime = moment().format('YYYY-MM-DD HH:mm:ss');//2021-01-20 16:42:20 当前时间字符串形式 const endTime = moment() .add(1, 'd')//'d' 时间单位: 天 .format('YYYY-MM-DD 00:00:00');//2021-01-21 00:00:00 当前时间加一天 //将指定时间戳转成时间字符串 const startTime2 = moment(00).format('YYYY-MM-DD HH:mm:ss');//2021-01-01 00:00:00 //moment 的时间单位如下 "year" | "years" | "y" | "month" | "months" | "M" | "week" | "weeks" | "w" | "day" | "days" | "d" | "hour" | "hours" | "h" | "minute" | "minutes" | "m" | "second" | "seconds" | "s" | "millisecond" | "milliseconds" | "ms"
- lodash( _ ) js常用工具库
let params = [{
name : 'aaa', age : 12 },{
name : 'bbb', age : 14 } ,{
name : 'CCC', age : 11 },{
name : 'ddd', age : 9 }] //G._.cloneDeep 深克隆 let newParams = G._.cloneDeep(params); //G._.get 数组取值,第一个参数为数组,第二个为path集合 //path 第一个值为索引,第二个为属性,类似与面包屑取值,层层向下取值 let getParams = G._.get(params,[1,"name"]);// bbb //G._.remove 便利数组,将满足条件的元素从数组中移除 G._.remove(params,param =>{
return param.age > 13 }) //将多维数组 递归为一维数组 let newArray = G._.flattenDeep([1, [2, [3, [4]], 5]]);//[1,2,3,4,5] //将数组按 size=2分组,无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块 let chunkArray = G._.chunk(newArray,2);//[[1,2],[3,4],[5]] //G._.uniq 数组元素去重 let uniqArr = G._.uniq([1,2,3,3,3,5,5]);//[1,2,3,5] //对长度小于2的字符串,进行前或后的拼接 0 补位,如果长度大于等于2则不处理 let start = G._.padStart("9", 2, '0');//09 let end = G._.padEnd("9", 2, '0');//90 let end2 = G._.padEnd("19", 2, '0');//19 let initList = [[{
text:"卧推"}],[{
text:"深蹲"}],[{
text:"侧平举"}]]; //将多维数组变成一维数组 let flatMap = G._.flatMapDeep(initList);//[{text:"卧推"},{text:"深蹲"},{text:"侧平举"}] //连个数组元素取交集 let interArr = G._.intersection([1,2,4,5],[2,3,4]);//[2,4] //集合对象按属性排序 按age 升序排列 let orderArr = G._.orderBy(newParams, ['age'], ['asc']) //按字段分组 const groupData = G._.groupBy(data.data, item => {
return item.operator; }); return "aaa"
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/140499.html