TS珠峰 004【学习笔记】

类型体操

type-1

// 内置
// Partial Required Readonly 修饰类型的
// Pick Omit 处理数据结构
// Exclude Extract 处理集合类型的
// Paramters RetrunValue infer
// 字符串类型,模板字符串`${}` + infer

PartialPropsOptional

// 1. Partial
// 2. Optional
// 3. Readonly
// 4. Pick
// 5. Omit

// Partial
// 将对象的属性变为可选的

interface Person {
  name: string;
  age: number;
  address: string;
}

type PartialPropsOptional<T extends Object, K extends keyof T> = Partial<
  Pick<T, K>
> &
  Omit<T, K>;

type Computed<T> = {
  [K in keyof T]: T[K];
};

type p1 = Computed<PartialPropsOptional<Person, 'age' | 'address'>>;

export {};

ExtractKeysByValueType

// 如何通过值类型拿到key
//将类型相同的进映射{name:"name",age:"never",address:"address"}
// name | never | address --> name | address
// 如何判断两个类型是否相同
type isEqual<T, U> = T extends U ? (U extends T ? true : false) : false;

type PickKeysByValue<T, V> = {
  // [K in keyof T]: T[K] extends V ? K : never;
  [K in keyof T]: isEqual<T[K], V> extends true ? K : never;
}[keyof T];

type OmitKeysByValue<T, V> = {
  [K in keyof T]: isEqual<T[K], V> extends true ? never : K;
}[keyof T];

type p2 = Computed<PickKeysByValue<Person, string>>; // 应该拿到name address
type p3 = Computed<OmitKeysByValue<Person, string>>; // 应该拿到age

// 模板字符串,里面有一个很重要的功能,重映射
type PickKeysByValue2<T, U> = {
  // 直接将对象的属性就给忽略掉了
  // 循环对象的key,看值的类型是否相同,如果相同留下这个key
  [K in keyof T as T[K] extends U ? K : never]: T[K];
};

type p4 = PickKeysByValue2<Person, string>;

export {};

OrType.ts

// 子类型互斥 OrType.ts
interface Man1 {
  fortune: string;
}
interface Man2 {
  funny: string;
}
interface Man3 {
  foreign: string;
}

type ManType = Man1 | Man2 | Man3; // 希望ManType只是其中的一种类型
let man: ManType = {
  fortune: '富有',
  funny: '风趣',
  foreign: '洋派',
}; // 希望ManType只是其中的一种类型
// man1-man2 将man1的属性标记成never +man2
// man2-man1 将man2的属性标记成never +man1
type DiscardType<T, U> = {
  [K in Exclude<keyof T, keyof U>]?: never;
};
type OrType<T, U> = (DiscardType<T, U> & U) | (DiscardType<U, T> & T);
type manType2 = OrType<Man3, OrType<Man1, Man2>>;
let man2: manType2 = {
  fortune: '富有',
};

export {};

交 差 并 补

// 对象的 交差并补
type A = {
  name: string;
  age: number;
  address: string;
};

type B = {
  name: string;
  male: boolean;
  address: number;
};

// 交集
type ObjIntersect<T extends object, U extends object> = Pick<
  T,
  Extract<keyof T, keyof U>
>;
type p1 = ObjIntersect<A, B>;

// 差集
type ObjectDiff<T extends object, U extends object> = Pick<
  T,
  Exclude<keyof T, keyof U>
>;
type R2 = ObjectDiff<A, B>;

// 补集 就是差集,要求是有父子关系
type ObjectCom<T extends U, U extends object> = Pick<
  T,
  Exclude<keyof T, keyof U>
>;
// type R3 = ObjectCom<B,A>

// 重写 以后面的类型为准 再加上以前比现在多的类型
type Overwrite<T extends object, U extends object> = ObjIntersect<U, T> &
  ObjectDiff<T, U>;
type Computed<T> = {
  [K in keyof T]: T[K];
} & {};
type R4 = Computed<Overwrite<A, B>>;
export {};

infer

// 模式匹配类型,抢断函数类型中参数的最后一个参数类型
function sum(a: string, b: string, c: number) {}
type LastParam<T extends (...args: any[]) => any> = T extends (
  ...args: infer P
) => any
  ? P extends [...any[], infer L]
    ? L
    : never
  : never;
type X = LastParam<typeof sum>;
export {};

type-2

首字母大写

// 首字母大写
// export type CapitalizeString<T> = T extends string
//   ? `${Capitalize<T & string>}`
//   : T;
// 默认情况,字符串的infer只匹配第一个字符
// 针对字符的infer 默认infer第一个指代的是第一个字符,后面的就是所有的
// 如果有分隔符号,指代的就是分隔符之前的
export type CapitalizeString<T> = T extends `${infer First}${infer Rest}`
  ? `${Capitalize<First>}${Rest}`
  : T;
type a1 = CapitalizeString<'handler'>;
type a2 = CapitalizeString<'parent'>;
type a3 = CapitalizeString<223>;

export {};

FirstChar

// 获取字符串的字面量中的第一个字符
type FirstChar<T extends string> = T extends `${infer L}${infer R}` ? L : T;
type A = FirstChar<'BFE'>; // B
type B = FirstChar<'dev'>; // BFE
type C = FirstChar<'234'>; // 234

LastChar

// lastchar
type LastChar<T, F = never> = T extends `${infer L}${infer R}` ? LastChar<R, L> : F;
type A1 = LastChar<'BFE'>; // E
type B1 = LastChar<'dev'>; // v
type C1 = LastChar<'234'>; // 4

字符串转元组

// string toTuple(元组)
type StringToTuple<T extends string> = T extends `${infer L}${infer R}` ? [L, ...StringToTuple<R>] : [];
type A2 = StringToTuple<'BFE'>; // ['B', 'F', 'E']
type B2 = StringToTuple<'dev'>; // ['d', 'e', 'v']
type C2 = StringToTuple<'234'>; // ['2', '3', '4']

元组转成字符串

// 元组转字符串
type TupleToString<T extends string[]> = T extends [infer L, ...infer R] ? `${L}${TupleToString<R>}` : '';
type A3 = TupleToString<['B', 'F', 'E']>; // 'BFE'
type B3 = TupleToString<['d', 'e', 'v']>; // 'dev'
type C3 = TupleToString<['2', '3', '4']>; // '234'

重复字符串

// repeat string
type RepeatString<
  T extends string,
  C extends number,
  A extends any[],
  F extends string = ''
> = C extends A['length'] ? F : RepeatString<T, C, [...A, any], `${F}${T}`>;
type A4 = RepeatString<'a', 3, [], ''>; // 'aaa'
type B4 = RepeatString<'a', 0, [], ''>; // ''
type C4 = RepeatString<'a', -1, [], ''>; // ''

split string 根据infer的左右分割,在左边放到数组中,右边递归,最终在结果集中增加无法匹配的即可

type SplitString<
  T extends string,
  S extends string,
  A extends any[]
> = T extends `${infer L}${S}${infer R}`
  ? SplitString<R, S, [L, ...A]>
  : [...A, T];
type A5 = SplitString<'handle-open-flag', '-', []>; // ['handle', 'open', 'flag']
type B5 = SplitString<'open-flag', '-', []>; // ['open', 'flag']
type C5 = SplitString<'BFE.dev.fe.js', '.', []>; // ['BFE', 'dev', 'fe', 'js']
type D5 = SplitString<'BFE.dev.fe.js', '-', []>; // ['BFE.dev.fe.js']

计算字符串长度

// 计算字符串字面量的长度
type StringLength<
  T extends string,
  A extends any[]
> = T extends `${infer L}${infer R}` ? StringLength<R, [L, ...A]> : A['length'];
type A6 = StringLength<'BFE.dev', []>; // 7
type B6 = StringLength<'dev', []>; // 3
type C6 = StringLength<'', []>; // 0

驼峰转连接符

// 驼峰命名转横杠命名
// 如何匹配大写? Capitalize<H> extends H
// 把大写变成--> -小写
type RemoveFirstLetter<T extends string> = T extends `-${infer V}` ? V : T;
type KebabCase<
  T extends string,
  F extends string = ''
> = T extends `${infer L}${infer R}`
  ? L extends Capitalize<L>
    ? KebabCase<R, `${F}-${Lowercase<L>}`>
    : KebabCase<R, `${F}${L}`>
  : RemoveFirstLetter<F>;
type aa1 = KebabCase<'HandleOpenFlag'>; // handle-open-flag
type aa2 = KebabCase<'OpenFlag'>; // open-flag

横杠命名转为驼峰命名

// 横杠命名转驼峰命名
type CamelCase<
  T extends string,
  F extends string = ''
> = T extends `${infer L}-${infer R1}${infer R2}`
  ? CamelCase<R2, `${F}${L}${Capitalize<R1>}`>
  : Capitalize<`${F}${T}`>;

type Bb1 = CamelCase<'handle-open-flag', ''>; // HandleOpenFlag
type Bb2 = CamelCase<'open-flag', ''>; // OpenFlag

object-->path

export type ObjectAccessPaths<
  T,
  F extends string = '',
  K = keyof T
> = K extends keyof T
  ? T[K] extends object
    ? // 如果当前的值是对象继续递归拼接,并且将当前解析的key 拼接到结果集中
      ObjectAccessPaths<T[K], `${F}${K & string}.`>
    : `${F}${K & string}` // 这里会丢失不是对象的最后一个key,
  : never;

function createI18n<Schema>(
  schema: Schema
): (path: ObjectAccessPaths<Schema>) => void {
  return (key: string) => {};
}

const i18n = createI18n({
  home: {
    topBar: {
      title: '首页',
      welcome: '欢迎来到首页',
    },
    bottomBar: {
      notes: '笔记',
    },
  },
  login: {
    title: '登录',
    username: '用户名',
    password: '密码',
    login: '登录',
  },
});
i18n('home.topBar.title');
// i18n('home.topBar.title');
i18n('home.bottomBar.notes');
i18n('login.title');
i18n('login.username');
i18n('login.password');
i18n('login.login');
i18n('login.xxx'); // 报错了

判断传入的字符串字面量类型中是否含有某个字符串

// 判断传入的字符串字面量类型中是否含有某个字符串
type Includes<
  T extends string,
  S extends string
> = T extends `${infer L}${S}${infer R}` ? true : false;
type a1 = Includes<'hello', 'h'>; // true
type a2 = Includes<'hello', 'e'>; // true
type a3 = Includes<'hello', 'a'>; // false
type a4 = Includes<'', ''>; //true T extends "" && S extends ""

trim 删除两边的空格

// trim
type TrimLeft<T extends string> = T extends ` ${infer R}` ? TrimLeft<R> : T;
type TrimRight<T extends string> = T extends `${infer R} ` ? TrimRight<R> : T;
type Trim<T extends string> = TrimRight<TrimLeft<T>>;
type a5 = Trim<'  .hello  '>; // '.hello'

replace

// 构建一个查找规则,找到后将左边和右边留起来${infer L}${S}${infer R}

type Replace<
  S extends string,
  From extends string,
  To extends string
> = From extends ''
  ? S
  : S extends `${infer L}${From}${infer R}`
  ? `${L}${To}${Replace<R, From, To>}`
  : S;

type aa1 = Replace<'hello world', 'world', 'walker'>; // 'hello walker'
type bb1 = Replace<'jwjw', 'jw', 'jiangwen'>; // 'jiangwenjiangwen'
type bb2 = Replace<'ha ha ha', 'ha', 'he'>; // 'he he he'
type aa2 = Replace<'jw', 'jw', 'jiangwen'>; // 'jiangwen'
type aa3 = Replace<'a', '', 'jiangwen'>; // 'jiangwenjiangwen'


type Replace1<T extends string,C extends string,RC extends string,F extends string = "">=
C extends ""? T extends ""?RC: `${RC}${T}`:T extends `${infer L}${C}${infer R}`? Replace1<R,C,RC,`${F}${L}${RC}`>:`${F}${T}`
type t1 = Replace1<"ha ha ha","ha","he">
type t2 = Replace1<"jw","jw","jiangwen">
type t3 = Replace1<"a","","jiangwen">
type t4 = Replace1<"","","jiangwen">
// 定义组件的监听事件类型
type EventType = {
  'handle-open': (flage: boolean) => true;
  'preview-item': (data: { item: any; index: number }) => true;
  'close-item': (data: { item: any; index: number }) => true;
};
/*
{
 onHandleOpen: (flage: boolean) => true;
 onPreviewItem: (data: { item: any; index: number }) => true;
 onCloseItem: (data: { item: any; index: number }) => true;
}
*/
// 实现type2
type ComponentEmitsType<T> = {
  [K in keyof T as `on${Capitalize<K>}`]: T[K] extends (...args: infer P) => any?(...args:P)=>void;
};
type EventType2 = ComponentEmitsType<EventType>;
// 转化为类型

元组的操作

// 计算元组类型的长度
type LengthOfTuple<T extends any[]> = T extends { length: infer L } ? L : never;
type A = LengthOfTuple<[1, 2, 3, 4, 5]>;
type B = LengthOfTuple<[]>;

// 元组第一项
type FirstItem<T extends any[]> = T extends [infer F, ...infer R] ? F : never;
type C = FirstItem<[1, 2, 3, 4, 5]>;
type D = FirstItem<[]>;

// 元组最后一项
type LastItem<T extends any[]> = T extends [...infer R, infer L] ? L : never;
type E = LastItem<[1, 2, 3, 4, 5]>;

// 移除元组第一项
type RemoveFirstItem<T extends any[]> = T extends [infer F, ...infer R]
  ? R
  : never;
type F = RemoveFirstItem<[1, 2, 3, 4, 5]>;
type G = RemoveFirstItem<[]>;

// 移除元组最后一项
type RemoveLastItem<T extends any[]> = T extends [...infer R, infer L]
  ? R
  : never;
type I = RemoveLastItem<[1, 2, 3, 4, 5]>;
type J = RemoveLastItem<[]>;

// push
type Push<T extends any[], V> = [...T, V];
type H = Push<[1, 2, 3, 4, 5], 6>;

// 反转元组 反转链表
type ReverseTuple<T extends any[]> = T extends [infer F, ...infer R]
  ? [...ReverseTuple<R>, F]
  : T;
type K = ReverseTuple<[1, 2, 3, 4, 5]>;
type L = ReverseTuple<[string, number, boolean]>;
type M = ReverseTuple<[]>;

// flatten 扁平化
type Flatten<T extends any[]> = T extends [infer F, ...infer R]
  ? [...(F extends any[] ? Flatten<F> : [F]), ...Flatten<R>]
  : T;
type N = Flatten<[1, [2, [3, [4, [5]]]]]>;
type O = Flatten<[[1, 2], [3, 4], [5, 6]]>;
type P = Flatten<[1]>;
type Q = Flatten<[]>;

// repeat
type Repeat<T, C extends number, F extends any[] = []> = C extends F['length']
  ? F
  : Repeat<T, C, [...F, T]>;
type A1 = Repeat<number, 3>; //[number,number,number]
type A2 = Repeat<string, 2>; //[string,string]
type A3 = Repeat<boolean, 1>; //[boolean]

// 过滤指定类型
type Filter<T extends any[], U, F extends any[] = []> = T extends [
  infer L,
  ...infer R
]
  ? // 如果需要则放到数组里,不需要返回原来
    Filter<R, U, [L] extends [U] ? [...F, L] : F>
  : F;
type A4 = Filter<[1, 'BEF', 2, true, 'dev'], number>; // [1,2]
type A5 = Filter<[1, 'BEF', 2, true, 'dev'], string>; // ["BEF","dev"]
type A6 = Filter<[1, 'BEF', 2, true, 'dev'], boolean>; // [true]
type A7 = Filter<[1, 'BEF', 2, any, 'dev'], string>; // ["BFE",any,'dev']

// FindIndex
type IsEqual<A, B, Success, Faile> = [A] extends [B]
  ? [B] extends [A]
    ? keyof A extends keyof B
      ? keyof B extends keyof A
        ? Success
        : Faile
      : Faile
    : Faile
  : Faile;
type FindIndex<T extends any[], U, F extends any[] = []> = T extends [
  infer L,
  ...infer R
]
  ? IsEqual<L, U, F['length'], FindIndex<R, U, [...F, L]>>
  : never;

type A8 = [any, never, 1, '2', true];
type A9 = FindIndex<A8, 1>; // 2
type A10 = FindIndex<A8, 3>; // never
type A11 = FindIndex<A8, true>; // 4
type A12 = FindIndex<A8, string>; // never

// 元组转成枚举,枚举对象中的值就是元素中某个元素中某个类型的字面量类型
type a1 = TupleToEnum<['MacOS', 'Windows', 'Linux']>;
// {readonly MacOS: "MacOS"; readonly Windows: "Windows"; readonly Linux: "Linux"}
// 如果传递了第二个参数为true,则枚举对象中值的类型是元素在元组中的index索引
type a2 = TupleToEnum<['MacOS', 'Windows', 'Linux'], true>;
// {readonly MacOS: 0; readonly Windows: 1; readonly Linux: 2}

type TupleToEnum<T extends any[], I extends boolean = false> = {
  readonly [K in T[number]]: IsEqual<I, true, FindIndex<T, K>, K>;
};

// slice
// 如果没有达到开头的长度,就要记录找到了多少个元素
type Slice<
  T extends any[],
  S extends number,
  E extends number = T['length'],
  SA extends any[] = [],
  SE extends any[] = [],
  F extends any[] = []
> = T extends [infer L, ...infer R]
  ? SA['length'] extends S
    ? SE['length'] extends E
      ? [...F, L]
      : Slice<R, S, E, SA, [...SE, null], [...F, L]>
    : Slice<R, S, E, [...SA, null], [...SE, null], F>
  : F;

type S1 = Slice<[any, never, 1, '2', true, boolean], 0, 2>; // [any,never,1]
type S2 = Slice<[any, never, 1, '2', true, boolean], 1, 3>; // [never,1,'2']
type S3 = Slice<[any, never, 1, '2', true, boolean], 1, 2>; // [never,1]
type S4 = Slice<[any, never, 1, '2', true, boolean], 2>; // [1,'2',true,boolean]
type S5 = Slice<[any], 2>; // []
type S6 = Slice<[], 0>; // []

// splice 删除并替换元素
type Splice<
  Arr extends any[],
  Start extends number,
  Count extends number = 0,
  Replace extends any[] = [],
  StartCount extends any[] = [],
  CountArr extends any[] = [],
  Result extends any[] = []
> = StartCount['length'] extends Start
  ? CountArr['length'] extends Count
    ? [...Result, ...Replace, ...Arr]
    : Arr extends [infer First, ...infer Rest]
    ? Splice<Rest, Start, Count, Replace, StartCount, [...CountArr, 0], Result>
    : Result
  : Arr extends [infer First, ...infer Rest]
  ? Splice<
      Rest,
      Start,
      Count,
      Replace,
      [...StartCount, 0],
      CountArr,
      [...Result, First]
    >
  : Result;

type SP1 = Splice<[string, number, boolean, null, undefined, never], 0, 2>; // [boolean,null,undefined,never]
type SP2 = Splice<[string, number, boolean, null, undefined, never], 1, 3>; // [string,undefined,never]
type SP3 = Splice<
  [string, number, boolean, null, undefined, never],
  1,
  2,
  [1, 2, 3]
>; // [string,1,2,3,null,undefined,never]

export {};

类型操作

// 获取对象类型中的可选属性的联合类型
// @ts-nocheck
type OptionalKeys<T> = keyof {
  [K in keyof T as T[K] extends Required<T>[K] ? never : K]: T[K];
};

type a1 = OptionalKeys<{
  foo: number | undefined;
  bar?: string;
  flag: boolean;
}>; // bar

type a2 = OptionalKeys<{ foo: number; bar?: string }>; // bar

type a3 = OptionalKeys<{ foo: number; flag: boolean }>; // never

type a4 = OptionalKeys<{ foo?: number; flag?: boolean }>; // foo|flag

type a5 = OptionalKeys<{}>; // never

// 获取对象类型中的必选属性
type PickRequired<T> = {
  [K in keyof T as T[K] extends Required<T>[K] ? K : never]: T[K];
};

type p1 = PickRequired<{
  foo: number | undefined;
  bar?: string;
  flag: boolean;
}>; // {foo:number|undefined, flag:boolean}

type p2 = PickRequired<{ foo: number; bar?: string }>; // {foo:number}

type p3 = PickRequired<{ foo: number; flag: boolean }>; // {foo:number,flag:boolean}

type p4 = PickRequired<{ foo?: number; flag?: boolean }>; // {}

type p5 = PickRequired<{}>; // {}

// 判断类型是否是 never
type IsNever<T> = [T] extends [never] ? true : false;

type A = IsNever<never>; // true
type B = IsNever<string>; // false
type C = IsNever<undefined>; // false
type D = IsNever<any>; // false

// 判断是否为没有属性的对象类型 {}
// @ts-nocheck
type x1 = keyof {}; // never

type IsEmptyType<T> = T extends object
  ? keyof T extends never
    ? true
    : false
  : false;

type EA = IsEmptyType<string>; // false
type EB = IsEmptyType<{ a: 3 }>; // false
type EC = IsEmptyType<{}>; // true
type ED = IsEmptyType<any>; // false
type EE = IsEmptyType<object>; // false
type EF = IsEmptyType<Object>; // false
type EG = IsEmptyType<unknown>; // false

// 判断类型是否是 any
// 可以将 unknown 赋予给 any
type IsAny<T> = unknown extends T ? true : false;

type IA = IsAny<string>; // false
type IB = IsAny<any>; // true
type IC = IsAny<unknown>; // false
type ID = IsAny<never>; // false

// @ts-nocheck
interface Action<T> {
  payload?: T;
  type: string;
}

interface Module {
  count: number;
  message: string;
  asyncMethod<T, U>(input: Promise<T>): Promise<Action<U>>;
  syncMethod<T, U>(action: Action<T>): Action<U>;
}

// 这个要求的结果
type Result = {
  asyncMethod<T, U>(input: T): Action<U>;
  syncMethod<T, U>(action: T): Action<U>;
};

type Connect<T> = {
  [K in keyof T]: T[K] extends (
    input: Promise<infer A>
  ) => Promise<Action<infer B>>
    ? (input: A) => Action<B>
    : T[K] extends (action: Action<infer A>) => Action<infer B>
    ? (action: A) => Action<B>
    : T[K];
};

type F = Connect<Module>;

// 将联合类型转换为交叉类型
// @ts-nocheck
type UnionToIntersection<U> = (
  U extends any ? (arg: U) => any : never
) extends (arg: infer I) => any
  ? I
  : never;

type UA = UnionToIntersection<{ a: string } | { b: string } | { c: string }>; // {a: string} & {b: string} & {c: string}

// 联合类型转换为元组类型
// @ts-nocheck
type UnionToTuple<T> = UnionToIntersection<
  T extends any ? (t: T) => T : never
> extends (_: any) => infer W
  ? [...UnionToTuple<Exclude<T, W>>, W]
  : [];

type a1 = UnionToTuple<1 | 2 | 3>; // [1,2,3]
type a2 = UnionToTuple<1 | 2 | boolean | string>; // [1,2,boolean,string]

export {};

主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://joyjs.cn/archives/4412

(0)
Walker的头像Walker
上一篇 2025年3月27日 15:01
下一篇 2025年4月6日 22:23

相关推荐

  • Go工程师体系课 protobuf_guide【学习笔记】

    Protocol Buffers 入门指南 1. 简介 Protocol Buffers(简称 protobuf)是 Google 开发的一种语言无关、平台无关、可扩展的结构化数据序列化机制。与 JSON、XML 等序列化方式相比,protobuf 更小、更快、更简单。 项目主页:https://github.com/protocolbuffers/prot…

    个人 2025年4月27日
    20600
  • 深入理解ES6 011【学习笔记】

    Promise与异步编程 因为执行引擎是单线程的,所以需要跟踪即将运行的代码,那些代码被放在一个任务队列中,每当一段代码准备执行时,都会被添加到任务队列中,每当引擎中的一段代码结束执行,事件循环会执行队列中的一下个任务。 Promise相当于异步操作结果占位符,它不会去订阅一个事件,也不会传递一个回调函数给目标函数,而是让函数返回一个Promise,就像这样…

    个人 2025年3月8日
    36200
  • 无畏前行,拳释力量 🥊💪

    拼搏,是一种态度 生活就像一场比赛,没有捷径可走,只有不断训练、突破、超越,才能站上属于自己的舞台。这不仅是一种对抗,更是一种自我的觉醒——敢于迎战,敢于挑战,敢于成为更强的自己。 运动中的拼搏精神 无论是拳击、跑步,还是力量训练,每一次出拳、每一次挥汗、每一次咬牙坚持,都是对身体与心灵的磨炼。拼搏不是单纯的对抗,而是一种态度——面对挑战,不退缩;面对失败,…

    个人 2025年2月26日
    41600
  • 深入理解ES6 007【学习笔记】

    Set集合与Map集合 在js中有g一个in运算符,其不需要读取对象的值就要以判断属性在对象中是否存在,如果存在就返回true。但是in运算符也会检索对象的原型,只有当对象原型为null时使用这个方法才比较稳妥。 Set集合 let set = new Set() set.add(5) set.add("5") console.log(s…

    个人 2025年3月8日
    39800
  • 深入理解ES6 012【学习笔记】

    代理(Proxy)和反射(Reflection)API 代理是一种可以拦截并改变底层javascript引擎操作的包装器,在新语言中通过它暴露内部运作对象,从而让开发者可以创建内建的对象。 代理陷阱 覆写的特性 默认特性 get 读取一个属性值 Reflect.get() set 写入一个属性值 Reflect.set() has in操作符 Reflect…

    个人 2025年3月8日
    39200

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
欢迎🌹 Coding never stops, keep learning! 💡💻 光临🌹