V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
az22c
V2EX  ›  React

(...args) => fn(...args) 有没有垃圾回收的问题?

  •  1
     
  •   az22c · 2020-09-11 11:53:03 +08:00 · 2346 次点击
    这是一个创建于 1538 天前的主题,其中的信息可能已经有所发展或是发生改变。
    js 函数柯里化或者实现语法糖经常用到这种逻辑:

    const adder = (...args) => dispatch(...args)。 // dispatch 可以任意普通函数。

    我看到 redux 源码里面也是这么用,甚至很多开源 react 项目是这么写。最近和面试官讨论,对方说这样会产生闭包,甚至有内存泄漏的风险。

    我回头 chrome 再测试调试一下,好像没有看到有闭包。不知道是不是我的理解有问题
    10 条回复    2020-09-12 13:27:58 +08:00
    KuroNekoFan
        1
    KuroNekoFan  
       2020-09-11 12:19:38 +08:00
    你面试官记混了吧,是 arguments object 有可能导致内存泄漏,而且跟闭包没关系
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
    FaiChou
        2
    FaiChou  
       2020-09-11 13:50:17 +08:00
    「有内存泄漏的风险」这句话怎么说都是正确的, 谁也不能保证浏览器是否释放应该被释放的变量. 但 「 (...args) => dispatch(...args)」这么写并没有内部变量呀, 有啥好泄漏的 ?

    不过还是要讲个例子(浏览器的 bug): https://bugs.chromium.org/p/chromium/issues/detail?id=315190

    var someClass = function() {
    console.log('some');
    };

    function getter() {
    var some = new someClass();
    if(true) {
    return function() { //I'm done with some and don't need it
    return null;
    };
    } else {
    return function() {
    return some;
    };
    }
    }

    window.f = getter();

    这个代码执行完理论上变量 some 会被回收, 因为 closure 没有 catch 住 some, 但通过 devtools 里 memory - [heap snapshot] 可以发现 变量 some 没有被 GC.

    所以, 这就是定义一个变量都有「有内存泄漏的风险」.
    az22c
        3
    az22c  
    OP
       2020-09-11 14:48:26 +08:00
    @FaiChou 你这个例子是特殊情况,编译的时候没法分析出 if true 。感觉是两回事,话题扯得比较远了。
    @KuroNekoFan 是 ,问题讨论集中到对 args 的引用上,有没有闭包。搞个测试代码测试一下,还是挺明显的
    soulmt
        4
    soulmt  
       2020-09-11 15:11:47 +08:00
    what 这会产生闭包? 应该说有可能会产生吧,es6 这种用法不是很多么,赶紧跑吧,这还面啥
    az22c
        5
    az22c  
    OP
       2020-09-11 15:57:25 +08:00
    @soulmt
    @KuroNekoFan
    好像明白了
    像 react-redux,这个“dispatch 函数”是作为函数参数传入本函数中,没有闭包问题。

    function mapDispatchToProps(dispatch) {
    return {
    adder: (...args) => dispatch('function name', ...args),
    }
    }

    connect(mapStateToProps, mapDispatchToProps)(Component)


    -------------------------

    而如果这个 dispatch 函数作为当前函数的内声明的函数,并且该函数返回 adder,是有闭包。
    KuroNekoFan
        6
    KuroNekoFan  
       2020-09-11 16:07:48 +08:00   ❤️ 1
    @az22c 按照闭包的定义,在一个 function 里在定义一个 function 就形成了一个闭包,但是闭包跟内存泄漏没有必然联系...
    finalwave
        7
    finalwave  
       2020-09-11 22:52:10 +08:00
    @FaiChou #2 这不是 V8 同一作用域函数共用内存和块状作用域内函数变量提升搞出来的问题嘛,换个引擎就好了(狗头
    FaiChou
        8
    FaiChou  
       2020-09-12 09:36:51 +08:00
    @finalwave #7 GC 是引擎自己实现的, 代码都是有 bug 的, 所以它有泄漏的风险 ( 逃
    usw
        9
    usw  
       2020-09-12 11:44:06 +08:00
    咋着,还指望把 dispatch 给你回收掉
    wxsm
        10
    wxsm  
       2020-09-12 13:27:58 +08:00 via iPhone
    遇到这种情况建议追问:具体是那一部分的内存泄漏?怎么个泄露法?怎么写才能不泄露?如果对方不懂,那就暴露了。如果真懂,那就学到了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1112 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:50 · PVG 06:50 · LAX 14:50 · JFK 17:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.