nazalewoyuanyi

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

  •  
  •   nazalewoyuanyi · Jun 20, 2022 · 5656 views
    This topic created in 1596 days ago, the information mentioned may be changed or developed.

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

    111

    Supplement 1  ·  Jun 21, 2022

    综合了一下大家的回答,感觉👇这个代码能不费力看懂~

    41 replies  •  2023-04-22 11:52:47 +08:00
    Yumwey
    Yumwey
    Jun 20, 2022
    1
    看看 koa 的源码吧,这是很基础的 compose 了,实现方式很多,递归,迭代都可以
    Biwood
    Biwood
    Jun 20, 2022 via Android
    2
    感觉还好,思路:遍历,使用.bind()把后一个 fn 作为参数绑定到前一个 fn 上,即前一个 fn 参数中的 next ,遍历完后执行第一个 fn 即可。

    猜测一下,expressjs 这类框架的中间件大概是类似原理吧。
    Yumwey
    Yumwey
    Jun 20, 2022
    4
    也可以看看 redux 的实现,应该都挺常见的
    Cbdy
    Cbdy
    Jun 20, 2022
    5
    一行代码的事情

    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))
    }
    nazalewoyuanyi
    nazalewoyuanyi
    OP
    Jun 20, 2022
    6
    @Cbdy 是怎么做到一下子写出来的...看来这道题真的很基础,面试官没说错。
    cyrbuzz
    cyrbuzz
    PRO
    Jun 20, 2022
    7
    ```
    const compose = arr => {
    const run = lastArr => {
    if (lastArr.length === 0) {
    return;
    }
    const first = lastArr.shift();

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

    这样?运行结果是 ok 的,没做检查。
    rabbbit
    rabbbit
    Jun 20, 2022
    8
    哎,想了十几分钟才有思路。现场肯定是写不出来了
    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));
    }
    nazalewoyuanyi
    nazalewoyuanyi
    OP
    Jun 20, 2022
    9
    @cyrbuzz 对的,我刚刚自己又尝试了一下,写出来的与你思路一致... 看样子我是能做出来的...唉
    cyrbuzz
    cyrbuzz
    PRO
    Jun 20, 2022
    10
    @zhaomeicheng

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

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

    // 递归
    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
    dinjufen
    Jun 20, 2022 via Android❤️3
    18
    sweetcola
    sweetcola
    Jun 20, 2022❤️4
    19
    综合上面回答的缩减版()

    const compose = ([fn, ...fns]) => () => fn?.(compose(fns))
    isbase
    isbase
    Jun 20, 2022
    20
    https://s2.loli.net/2022/06/20/UiwjuvXhOoVeLAm.png

    Github Copilot 自动补全的代码
    KMpAn8Obw1QhPoEP
    KMpAn8Obw1QhPoEP
    Jun 20, 2022 via Android
    21
    @sweetcola 很极致 我喜欢
    skies457
    skies457
    Jun 20, 2022
    22
    const compose = ((self, [fn, ...fns]) => () => fn?.(self(self, fns)))((self, [fn, ...fns]) => () => fn?.(self(self, fns)), arr)

    还可以升级一下难度,只使用匿名函数(逃
    skies457
    skies457
    Jun 20, 2022
    23
    const compose = arr => ((self, [fn, ...fns]) => () => fn?.(self(self, fns)))((self, [fn, ...fns]) => () => fn?.(self(self, fns)), arr)

    少了 arr => (
    dasbn
    dasbn
    Jun 20, 2022
    24
    @skies457 Y= f => (x => v => f(x(x))(v)) (x => v => f(x(x))(v))

    提取出你的 Y (
    molvqingtai
    molvqingtai
    Jun 20, 2022 via Android
    25
    洋葱圈模型还挺实用的,koa 就不用说了,比如前端使用的 redux 、vue-router 内部实现都是使用洋葱模型

    我也这种模式封装了一个 http 客户端:
    https://github.com/molvqingtai/resreq
    chezs66
    chezs66
    Jun 20, 2022
    26
    这就是栈呀。。。无非是自己写一个栈,或用 js 自带的栈
    zyxyz123
    zyxyz123
    Jun 20, 2022
    27
    const compose = (arr) => {
    if (arr.length === 0) {
    return () => {}
    }
    return () => {
    arr[0](compose(arr.slice(1)))
    }
    }
    otakustay
    otakustay
    Jun 20, 2022
    28
    const compose = handlers => handlers.reduceRight((out, v) => () => v(out), () => {});

    手写倒有点难,电脑敲再简单调试一下下可以
    Agassiz
    Agassiz
    Jun 21, 2022 via iPhone
    29
    洋葱模型
    walpurgis
    walpurgis
    Jun 21, 2022
    30
    middlewares = [fn1,fn2,fn3]
    compose 展开后是这样
    fn = () => fn1(() => fn2(() => fn3(() => {})));

    暴力拼接法

    function compose(arr) {
    const fn = arr.pop();
    let composed = () => fn(() => {});
    while (arr.length > 0) {
    const fn = arr.pop();
    composed = ((next) => () => fn(next))(composed)
    };
    return composed;
    }
    wanacry
    wanacry
    Jun 21, 2022 via iPhone
    31
    这是啥玩意 我也会 js 但是为啥我都看不懂
    MonkeyD1
    MonkeyD1
    Jun 21, 2022
    32
    @wanacry 哈哈 ➕1 我也是
    banmuyutian
    banmuyutian
    Jun 21, 2022
    33
    才疏学浅,请教下这个洋葱模型是不是类似于 Spring Boot 的堆栈?
    danhua
    danhua
    Jun 21, 2022
    34
    为啥我第一眼感觉可以用异步来解决,不过异步比上面大佬们给出的方法要麻烦多了。
    dtdths1
    dtdths1
    Jun 21, 2022
    35
    洋葱圈模型
    ryougifujino
    ryougifujino
    Jun 21, 2022
    36
    function compose(arr) {
    let next = function () {
    }
    arr.reverse().forEach(fn => {
    const nextFn = next
    next = function () {
    fn(nextFn)
    }
    })
    return next
    }
    ryougifujino
    ryougifujino
    Jun 21, 2022
    37
    @ryougifujino #36 个人感觉我这个思路很简单,确实就是洋葱圈模型。next 顾名思义,就是下一次要执行的函数,所以核心思路就是把下一次的函数放到 next 中去就行了。
    nazalewoyuanyi
    nazalewoyuanyi
    OP
    Jun 21, 2022
    38
    @ryougifujino 说真的,我看不懂😂
    Lenic
    Lenic
    Jun 25, 2022
    39
    建议看下 Array.prototype.reduce 方法
    usdc
    usdc
    Aug 3, 2022
    40
    我感觉这道题是需要多次运行 fn() 可以再出输入 1 2 3 3.1 2.1 1.1 吧 难道是我想多了?
    @zhaomeicheng
    @ryougifujino
    @Cbdy
    @cyrbuzz
    houchangxiaowang
    houchangxiaowang
    Apr 22, 2023
    41
    图片挂了,重新帖下?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   5061 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 81ms · UTC 08:54 · PVG 16:54 · LAX 00:54 · JFK 03:54
    ♥ Do have faith in what you're doing.