particlec
0.01D
V2EX  ›  问与答

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

  •  
  •   particlec · May 25, 2022 · 3995 views
    This topic created in 1623 days ago, the information mentioned may be changed or developed.

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

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

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


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

    这种写法不好,codereview 要被骂死的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1716 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 47ms · UTC 17:30 · PVG 01:30 · LAX 09:30 · JFK 12:30
    ♥ Do have faith in what you're doing.