前端大佬能当场写出这道题吗?

2022-06-20 18:02:49 +08:00
 zhaomeicheng

当场没写出来,面试官劝我别紧张,说这道题很基础,可是面试后自己在这也没写出来...

4249 次点击
所在节点    前端开发
41 条回复
Yumwey
2022-06-20 18:24:36 +08:00
看看 koa 的源码吧,这是很基础的 compose 了,实现方式很多,递归,迭代都可以
Biwood
2022-06-20 18:24:56 +08:00
感觉还好,思路:遍历,使用.bind()把后一个 fn 作为参数绑定到前一个 fn 上,即前一个 fn 参数中的 next ,遍历完后执行第一个 fn 即可。

猜测一下,expressjs 这类框架的中间件大概是类似原理吧。
Yumwey
2022-06-20 18:25:36 +08:00
Yumwey
2022-06-20 18:27:05 +08:00
也可以看看 redux 的实现,应该都挺常见的
Cbdy
2022-06-20 18:28:42 +08:00
一行代码的事情

export function compose(middlewares = (ctx, next) => (void 0)) {
if (!middlewares || !middlewares.length) {
return ctx => (void 0)
}
return ctx => middlewares[0](ctx, () => compose(middlewares.slice(1))(ctx))
}
zhaomeicheng
2022-06-20 18:36:21 +08:00
@Cbdy 是怎么做到一下子写出来的...看来这道题真的很基础,面试官没说错。
cyrbuzz
2022-06-20 18:42:19 +08:00
```
const compose = arr => {
const run = lastArr => {
if (lastArr.length === 0) {
return;
}
const first = lastArr.shift();

first(() => run(arr));
};
return () => {
run(arr);
};
};
```

这样?运行结果是 ok 的,没做检查。
rabbbit
2022-06-20 18:56:16 +08:00
哎,想了十几分钟才有思路。现场肯定是写不出来了
function compose(arr) {
const next = (fn = (() => {}), arr) => {
fn(next.bind(this, arr[0], arr.slice(1)));
};
return next.bind(this, arr[0], arr.slice(1));
}
zhaomeicheng
2022-06-20 18:57:17 +08:00
@cyrbuzz 对的,我刚刚自己又尝试了一下,写出来的与你思路一致... 看样子我是能做出来的...唉
cyrbuzz
2022-06-20 19:01:07 +08:00
@zhaomeicheng

hh ,我一开始也没有思路,不过有个好队友提示。
TWorldIsNButThis
2022-06-20 19:06:45 +08:00
swr 的 middleware 就是这个结构
其他前端框架应该有不少类似的
des
2022-06-20 19:18:46 +08:00
忘了在哪里看到的了
arr.reverse().reduce((a, b) => () => b(a), Function.prototype)()
rabbbit
2022-06-20 19:20:00 +08:00
哪里有类似 Leetcode 能刷这种题的题库吗?
Cbdy
2022-06-20 19:46:26 +08:00
如果觉得 JS 版本太难懂,可以看一下 Java 版本
https://github.com/cbdyzj/nanometer/blob/main/common/src/main/java/nano/support/Onion.java
enchilada2020
2022-06-20 19:52:20 +08:00
```JS
const compose = ([f, ...arr]) => arr.length
? () => f(compose(arr))
: () => f?.(() => { });
```
enchilada2020
2022-06-20 20:02:27 +08:00
没想到还有更简单的

```JS
const compose = arr => arr.reduceRight((acc, cur) => () => cur(acc), () => { });
```
tyx1703
2022-06-20 20:03:36 +08:00
想了十几分钟,代码倒是简单,思路很重要。估计我面试时也会紧张写不出来。

// 递归
function compose(middlewares) {
if (middlewares.length === 0) {
return () => {}
}
const middleware = middlewares.shift()
return middleware.bind(null, compose(middlewares))
}

// 迭代
function compose(middlewares) {
let res;
for (let i = middlewares.length - 1; i >= 0; i--) {
if (!res) {
res = middlewares[i].bind(null, () => {})
} else {
res = middlewares[i].bind(null, res)
}
}
return res;
}
dinjufen
2022-06-20 20:10:45 +08:00
sweetcola
2022-06-20 20:25:21 +08:00
综合上面回答的缩减版()

const compose = ([fn, ...fns]) => () => fn?.(compose(fns))
isbase
2022-06-20 21:21:58 +08:00
https://s2.loli.net/2022/06/20/UiwjuvXhOoVeLAm.png

Github Copilot 自动补全的代码

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/860936

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX