在 Javascript 中,大块一次性数据放在函数中返回是不是比放在变量更省内存? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
june4
V2EX    前端开发

在 Javascript 中,大块一次性数据放在函数中返回是不是比放在变量更省内存?

  •  
  •   june4 304 天前 1935 次点击
    这是一个创建于 304 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如说在 Javascript 中,我有一些原始数据,用于构造一个最终对象,所以这个 data 一次性用完就没用了。

    const data = { ... } const targetObj = build(data)  

    那我是象上面那样放在一个模块变量里好呢,还是用个函数返回好?

    const data = () => ({ ... }) const targetObj = build(data()) 

    如果这些数据比较大,用了函数,是不是省了数据一份在内存中复制品?

    8 条回复    2025-03-01 21:20:17 +08:00
    dumbass
        1
    dumbass  
       304 天前
    如果会对 data 进行变更那还是用函数返回对象的形式吧,不然追踪那里改了 data 将是一件头痛的事
    Linho1219
        2
    Linho1219  
       304 天前 via Android   1
    不用管,怎么舒服怎么写
    JS 有完善的垃圾回收机制,引擎会提前读代码做优化,知道你哪些用哪些不用。即使当前作用域还在,如果你后面 data 不用了就会自动回收掉
    (你想想你代码里多少个闭包,理论上这些闭包都会完整保留当前作用域,实际上不会,后面没用的就直接回收了)
    不要用这种“微优化”折腾自己,关注代码逻辑才是最重要的。写 JS 只要大体路线没错性能一般不是大问题
    ruxuan1306
        3
    ruxuan1306  
       304 天前
    没省,对象传参是传址,不是传值,后者反而构造 Object 时多了一层构造和调用函数的开销。
    june4
        4
    june4  
    OP
       303 天前
    @Linho1219 好吧,有空还是得亲自试验一下。你说的模块全局变量也会回收,我是不太相信。毕竟模块作用域可永不会消失,它引用的变量怎么就回收了。如果是小对象就算了,我这边这个数据对象有点大,如果微操一下能省点内存不是更好。


    @ruxuan1306 这和传址没关系吧?你也可以把 data 当 string 类型,用于生成一个页面,生成后原来的 string 就不要了。
    ruxuan1306
        5
    ruxuan1306  
       302 天前
    @june4 string 是值类型,object 是引用类型,看起来这是你的模糊点,找个 AI 聊聊
    june4
        6
    june4  
    OP
       301 天前
    @ruxuan1306 你都没搞清楚我说的是什么。你拿一个字符串模板生成另一个,是不是二个完全不同的字符串了?和值和引用有什么关系呢?
    ruxuan1306
        7
    ruxuan1306  
       298 天前
    @june4 我不知道你的水平,不知道如下表述你能否看懂:

    const data = { ... } // 在堆上申请了一个空间,储存对象 { ... },并把指针记为 data
    const targetObj = build(data) // 向 build 传入 data 这个指针,build 函数在堆上申请了一个新的空间,储存构造出的对象,并将其指针返回,被你记为 targetObj
    // build 执行完后,data 指向源对象,targetObj 指向构造出的对象,gc 回收不了任何对象

    const data = () => ({ ... }) // 在堆上申请了一个空间,储存函数 () => ({ ... }),并把指针记为 data
    const targetObj = build(data()) // 调用 data 函数,data 函数在堆上申请了一个新的空间,储存构造出的对象 { ... },并将其指针返回;向 build 函数传入 data 返回的对象指针,build 函数在堆上申请了一个新的空间,储存构造出的对象,并将其指针返回,被你记为 targetObj
    // build 执行完成后其栈空间会被释放,那个存在于其形参的指向堆源对象的指针也被释放,源对象将在稍后被 gc 回收; targetObj 指向构造出的对象


    这两种写法,前者在执行完成后内存占用高( gc 无法回收源对象),后者在执行过程中峰值内存占用高(多出一个函数对象的空间)


    另外你一直在用 string 类比,要说明的是,在 Javascript 中基本类型包括 string 是按值传递的,传入函数时是拷贝,而不是像 object 一样是指针。
    june4
        8
    june4  
    OP
       298 天前
    @ruxuan1306 我不就说 data 这个全局变量不会回收嘛。
    另外 js 又不是 C++, string 传进去绝对不可能是复制一份内存,毕竟 js 没有修改字符串内容的能力为什么要传一份拷贝。

    至于哪种占用内存高还不一定,比如万一浏览器会在加载运行完 js 文件后释放了 js 源码所占内存,但函数可能有特殊,因为函数的 toString 会得到源码,所以函数可能会把对应源码复制函数对象,这样把 data 弄成函数省下的内存又在函数源码上完全找补回来了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1646 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 16:19 PVG 00:19 LAX 08:19 JFK 11:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86