# 方法顺序执行,不论同步还是异步
以下代码实现方法顺序执行,不论同步还是异步
let result;
for (const f of [func1, func2, func3]) {
result = await f(result);
}
/* use last result (i.e. result3) */
1
2
3
4
5
2
3
4
5
更老版本的写法:
const applyAsync = (acc, val) => acc.then(val);
const composeAsync =
(...funcs) =>
(x) =>
funcs.reduce(applyAsync, Promise.resolve(x));
const transformData = composeAsync(func1, func2, func3);
const result3 = transformData(data);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
参考:MDN: 使用Promise (opens new window)
# 闭包缓存计算结果,提高性能
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key] !== undefined) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
const memoizedFibonacci = memoize(fibonacci);
console.log(memoizedFibonacci(10)); // 输出 55
console.log(memoizedFibonacci(20)); // 输出 6765
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
在这个例子中,memoize
函数通过闭包缓存了计算结果,提高了递归函数的性能。
# 闭包实现函数柯里化
通用的函数柯里化工具函数,注意这里没有处理this
的指向
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn(...args);
}
return function (...nextArgs) {
return curried(...args, ...nextArgs);
};
};
}
function sum(a,b,c){
return a+b+c;
}
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
console.log(curriedSum(1, 2)(3)); // 6
console.log(curriedSum(1)(2, 3)); // 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# TypeScript
# 枚举+位运算进行状态判断
枚举+位运算进行状态判断与运算
enum AnimalFlags {
None = 0,
HasClaws = 1 << 0,
CanFly = 1 << 1
}
interface Animal {
flags: AnimalFlags;
[key: string]: any;
}
function printAnimalAbilities(animal: Animal) {
var animalFlags = animal.flags;
if (animalFlags & AnimalFlags.HasClaws) {
console.log('animal has claws');
}
if (animalFlags & AnimalFlags.CanFly) {
console.log('animal can fly');
}
if (animalFlags == AnimalFlags.None) {
console.log('nothing');
}
}
var animal = { flags: AnimalFlags.None };
printAnimalAbilities(animal); // nothing
animal.flags |= AnimalFlags.HasClaws;
printAnimalAbilities(animal); // animal has claws
animal.flags &= ~AnimalFlags.HasClaws;
printAnimalAbilities(animal); // nothing
animal.flags |= AnimalFlags.HasClaws | AnimalFlags.CanFly;
printAnimalAbilities(animal); // animal has claws, animal can fly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Animal 有多种状态时判断、运算十分简洁
假如让我来写的话,不用枚举+位运算的话可能实现如下
type AnimalFlags = 'None' | 'HasClaws' | 'CanFly';
interface Animal {
flags: AnimalFlags[];
[key: string]: any;
}
function printAnimalAbilities(animal: Animal) {
var animalFlags = animal.flags;
if (!animalFlags || animalFlags.includes('None')) {
return 'nothing';
}
if (animalFlags.includes('HasClaws')) {
console.log('animal has claws');
}
if (animalFlags.includes('CanFly')) {
console.log('animal can fly');
}
}
var animal: Animal = { flags: ['None'] };
printAnimalAbilities(animal); // nothing
animal.flags = ['HasClaws'];
printAnimalAbilities(animal); // animal has claws
animal.flags = ['None'];
printAnimalAbilities(animal); // nothing
animal.flags = ['HasClaws', 'CanFly'];
printAnimalAbilities(animal); // animal has claws, animal can fly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
运算不太方便,比如状态是['HasClaws', 'CanFly']
, 想移除Fly状态需要进行数组操作,比位运算麻烦许多
参考:深入理解 TypeScript:枚举 (opens new window)
# React 导出 useImperativeHandle 的声明
定义:
type CountdownProps = {}
type CountdownHandle = {
start: () => void,
}
const Countdown: React.ForwardRefRenderFunction<CountdownHandle, CountdownProps> = (
props,
forwardedRef,
) => {
React.useImperativeHandle(forwardedRef, ()=>({
start() {
alert('Start');
}
}));
return <div>Countdown</div>;
}
export default React.forwardRef(Countdown);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在上层组件中常想知道子组件useImperativeHandle
的定义,可以这么写:
const App: React.FC = () => {
// 这个类型等于 `CountdownHandle`,但不需要手动 import CountdownHandle
type CountDownRef = React.ElementRef<typeof Countdown>;
const ref = React.useRef<CountDownRef>(null); // assign null makes it compatible with elements.
return (
<Countdown ref={ref} />
);
};
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
CountDownRef
这个类型等于 CountdownHandle
,但不需要手动 import CountdownHandle
参考:stackoverflow (opens new window)
# +
-
修饰符
# +
-
修饰符可以添加或去掉readonly
和 ?
,如
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property];
};
type LockedAccount = {
readonly id: string;
readonly name: string;
};
type UnlockedAccount = CreateMutable<LockedAccount>;
// UnlockedAccount 等效于
type UnlockedAccount = {
id: string;
name: string;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 通过as
重新映射类型
在TypeScript 4.1及更高版本中,可以在映射类型中使用as子句重新映射映射类型中的键,形式如下:
type MappedTypeWithNewProperties<Type> = {
[Properties in keyof Type as NewKeyType]: Type[Properties]
}
1
2
3
2
3
# 示例一,根据已知类型的键映射出新类型键
Capitalize (opens new window): 转换字符串类型第一个字母为大写
type Getters<Type> = {
[Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property]
};
interface Person {
name: string;
age: number;
location: string;
}
type LazyPerson = Getters<Person>;
// 最终LazyPerson 等效于
type LazyPerson = {
getName: () => string;
getAge: () => number;
getLocation: () => string;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 示例二:映射任意联合类型
如:映射联合对象类型,并以类型的Value为新类型的key
type EventConfig<Events extends { kind: string }> = {
[E in Events as E["kind"]]: (event: E) => void;
}
type SquareEvent = { kind: "square", x: number, y: number };
type CircleEvent = { kind: "circle", radius: number };
type Config = EventConfig<SquareEvent | CircleEvent>
// 最终config等效于
type Config = {
square: (event: SquareEvent) => void;
circle: (event: CircleEvent) => void;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15