V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
particlec
V2EX  ›  问与答

前端问题 为什么我的 fliter 能改变原数组?网上全部都是 filter 不改变原数组....

  •  
  •   particlec · 2022-05-25 09:18:35 +08:00 · 2887 次点击
    这是一个创建于 944 天前的主题,其中的信息可能已经有所发展或是发生改变。

    const [selectProductKey, setSelectProductKey] = useState([]);

    // 搜索框 key 匹配数组 productKey const matchProductKey = key => { let temporaryArr = [...productKeyArr]; temporaryArr.filter(obj => obj.slice(key) !== -1); setSelectProductKey(temporaryArr); };

    onSearch={e => {matchProductKey(e);}}

    // 这里的 selectProductKey 数组确实被筛选了 {selectProductKey.map(key => (<Select.Option value={key}>{key}</Select.Option>))}

    27 条回复    2022-05-26 09:49:01 +08:00
    liujunhn
        1
    liujunhn  
       2022-05-25 09:24:09 +08:00 via iPhone
    你不是已经用 setSelectProductKey(temporaryArr)把 filter 之后的数组给到 select Product Key 了吗?
    particlec
        2
    particlec  
    OP
       2022-05-25 09:27:28 +08:00
    // 这里 使用了 filter ,按道理 temporaryArr 不会被改变
    temporaryArr.filter(obj => obj.slice(key) !== -1);

    // selectProductKey 按道理也不会改变啊
    setSelectProductKey(temporaryArr);
    particlec
        3
    particlec  
    OP
       2022-05-25 09:34:57 +08:00
    const [selectProductKey, setSelectProductKey] = useState([]);

    // 这是一个搜索框的功能,通过 key 模糊筛选
    const matchProductKey = key => {
    let temporaryArr = [...productKeyArr];
    // 这里 使用了 filter ,按道理原数组 temporaryArr 不会被改变
    temporaryArr.filter(obj => obj.slice(key) !== -1);
    // 如果原数组没有改变 selectProductKey 也不会改变
    setSelectProductKey(temporaryArr);
    };


    matchProductKey(e);


    // 但是实际界面 这里 selectProductKey 确实数据过滤了
    {selectProductKey.map(key => (
    <Select.Option value={key}>{key}</Select.Option>
    ))}
    重新描述一下,第一次发帖问题顺序有点乱
    shabbyin
        4
    shabbyin  
       2022-05-25 09:36:07 +08:00   ❤️ 1
    原数组没改变
    你用 setSelectProductKey 方法把过滤后的新数组通过设置为新的 state 指向了
    此时你访问的 state 已经是新数组了 老数组你没有保存其堆地址的话 就再也访问不到了
    particlec
        5
    particlec  
    OP
       2022-05-25 09:40:21 +08:00
    setSelectProductKey(temporaryArr) state 不是会指向 temporaryArr 吗?为啥会指向新数组呢
    wu67
        6
    wu67  
       2022-05-25 09:41:32 +08:00
    array 的高级方法不改变原值, 意思是: 直接改基础类型 无效. 直接改引用 无效. 但是如果你改引用类型里面的 下标 /属性 值, 有效.
    rabbbit
        7
    rabbbit  
       2022-05-25 09:47:18 +08:00
    let temporaryArr = [...productKeyArr];
    这里创建了新数组 temporaryArr
    setSelectProductKey(temporaryArr);
    这里新数组被赋值给 selectProductKey
    shabbyin
        8
    shabbyin  
       2022-05-25 09:47:44 +08:00
    @particlec
    这块有一个比较可疑的点
    filter 遍历的元素应该不是一个基础类型数据,而是引用类型的数据
    另外 你这个数组结构我属实有点没看懂
    filter 里用了 obj.slice 方法,是不是可以认为 obj 是一个数组
    那么按道理说你这个 selectProductKey 应该是一个二维数组吧
    那么这种情况下怎么做到一层 map 实现 dom 渲染的
    particlec
        9
    particlec  
    OP
       2022-05-25 09:51:30 +08:00
    console.log(temporaryArr);
    temporaryArr =['a1k8ySyJMPn', 'a1mXxl1AJOa', 'a1T2vgkO3L7', 'a1xaURWP4fN', 'a1oCgqebiVr', 'a1OSLcORuwH', 'a1StepeOwMD', 'a1oAnKZ7Clp', 'a1M4rSzH9wr', 'a1Y2RSRhB8b']
    Shy07
        10
    Shy07  
       2022-05-25 09:52:30 +08:00   ❤️ 1
    const productKeyArr = ['010', '020', '030']
    const temporaryArr = [...productKeyArr]
    temporaryArr.filter(obj => obj.includes('2'))
    console.log(temporaryArr)

    代码精简一下大概这样子,浏览器运行结果是 ['010', '020', '030']
    这部分没问题,建议看看 productKeyArr 是不是被修改了
    rabbbit
        11
    rabbbit  
       2022-05-25 09:53:31 +08:00
    建议找个 codepen 之类的贴下代码
    particlec
        12
    particlec  
    OP
       2022-05-25 09:56:32 +08:00
    嗯,slice 确实要改成 includes ,主要是那个引用问题还不是很理解
    fengfuliu
        13
    fengfuliu  
       2022-05-25 10:00:40 +08:00
    @particlec 问题就是你调用了 slice 导致的 slice 返回被裁减过的数组 因为是浅拷贝 影响到了 temporaryArr 吧
    sweetcola
        14
    sweetcola  
       2022-05-25 10:01:23 +08:00
    slice 返回的是数组,数组 !== -1 那不是全部 true 吗...
    particlec
        15
    particlec  
    OP
       2022-05-25 10:01:35 +08:00
    我打印了一下,发现原数组 temporaryArr 确实没有改变,就是 setSelectProductKey(temporaryArr);为啥没指向原数组
    sweetcola
        16
    sweetcola  
       2022-05-25 10:06:24 +08:00
    @particlec 你用了 Spread 语法([...productKeyArr]),temporaryArr 就已经是一个新的数组了,不会指向原数组。
    particlec
        17
    particlec  
    OP
       2022-05-25 10:08:48 +08:00
    不是 slice 的问题,换成 includes 也会出现同样的问题,应该跟 setSelectProductKey 有关
    particlec
        18
    particlec  
    OP
       2022-05-25 10:23:21 +08:00
    @shabbyin “老数组你没有保存其堆地址的话 就再也访问不到了” 请教 老数组为啥访问不到,setSelectProductKey 为什么会指向新数组呢
    disk
        19
    disk  
       2022-05-25 11:45:11 +08:00
    代码不全,看不出更多东西,建议自己跑个 debug 看下
    zhaomeicheng
        20
    zhaomeicheng  
       2022-05-25 14:13:55 +08:00
    主题支持 Markdown 格式的,建议代码别直接贴,看不清楚...
    stillsilly
        21
    stillsilly  
       2022-05-25 17:11:43 +08:00
    filter 改不改变原数组,要看你代码的写法。
    一般正常的用法是,返回一个新数组,不改变原数组。
    但是如果你在函数里写了有副作用的语句,比如 item.name = item.name + 111 、用了有副作用的 api push pop shift unshift reverse sort splice 之类的,那原数组当然改变了。
    filter 只是做一次循环迭代而已,跟 for 循环 forEach 循环 map 类似,你在 for 循环里也可以只做读操作,那就没有改原数组。也可以有写的操作,就改了原数组……
    stillsilly
        22
    stillsilly  
       2022-05-25 17:16:35 +08:00
    stillsilly
        23
    stillsilly  
       2022-05-25 17:24:40 +08:00
    temporaryArr.filter(obj => obj.slice(key) !== -1)
    这一句没有改原数组,slice 没有副作用


    如果你的数组变了,应该是其它地方改的
    robinlovemaggie
        24
    robinlovemaggie  
       2022-05-25 22:50:49 +08:00
    分明是你在某处改了 productKeyArr ,却把锅甩给 filter ,非要给你看下 filter 的源码实现你才相信吗?
    https://imgur.com/5S9lZ8c
    ciaoly
        25
    ciaoly  
       2022-05-25 23:58:54 +08:00 via Android
    @stillsilly 这个图里的测试代码是不是少打了一个等号?
    particlec
        26
    particlec  
    OP
       2022-05-26 08:34:53 +08:00
    全部相关的代码已经在三楼了,selectProductKey 的值只在三楼 setSelectProductKey 处改变过,,temporaryArr 就是一个 string[]结构,我已经打印了 temporaryArr 原数组没有改变
    stillsilly
        27
    stillsilly  
       2022-05-26 09:49:01 +08:00
    @ciaoly
    没有啊,就是想改 item. name 的值,给它重新赋值一下

    这种写法不好,codereview 要被骂死的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1025 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 20:46 · PVG 04:46 · LAX 12:46 · JFK 15:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.