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

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

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

    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  
       131 天前 via iPhone
    你不是已经用 setSelectProductKey(temporaryArr)把 filter 之后的数组给到 select Product Key 了吗?
    particlec
        2
    particlec  
    OP
       131 天前
    // 这里 使用了 filter ,按道理 temporaryArr 不会被改变
    temporaryArr.filter(obj => obj.slice(key) !== -1);

    // selectProductKey 按道理也不会改变啊
    setSelectProductKey(temporaryArr);
    particlec
        3
    particlec  
    OP
       131 天前
    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  
       131 天前   ❤️ 1
    原数组没改变
    你用 setSelectProductKey 方法把过滤后的新数组通过设置为新的 state 指向了
    此时你访问的 state 已经是新数组了 老数组你没有保存其堆地址的话 就再也访问不到了
    particlec
        5
    particlec  
    OP
       131 天前
    setSelectProductKey(temporaryArr) state 不是会指向 temporaryArr 吗?为啥会指向新数组呢
    wu67
        6
    wu67  
       131 天前
    array 的高级方法不改变原值, 意思是: 直接改基础类型 无效. 直接改引用 无效. 但是如果你改引用类型里面的 下标 /属性 值, 有效.
    rabbbit
        7
    rabbbit  
       131 天前
    let temporaryArr = [...productKeyArr];
    这里创建了新数组 temporaryArr
    setSelectProductKey(temporaryArr);
    这里新数组被赋值给 selectProductKey
    shabbyin
        8
    shabbyin  
       131 天前
    @particlec
    这块有一个比较可疑的点
    filter 遍历的元素应该不是一个基础类型数据,而是引用类型的数据
    另外 你这个数组结构我属实有点没看懂
    filter 里用了 obj.slice 方法,是不是可以认为 obj 是一个数组
    那么按道理说你这个 selectProductKey 应该是一个二维数组吧
    那么这种情况下怎么做到一层 map 实现 dom 渲染的
    particlec
        9
    particlec  
    OP
       131 天前
    console.log(temporaryArr);
    temporaryArr =['a1k8ySyJMPn', 'a1mXxl1AJOa', 'a1T2vgkO3L7', 'a1xaURWP4fN', 'a1oCgqebiVr', 'a1OSLcORuwH', 'a1StepeOwMD', 'a1oAnKZ7Clp', 'a1M4rSzH9wr', 'a1Y2RSRhB8b']
    Shy07
        10
    Shy07  
       131 天前   ❤️ 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  
       131 天前
    建议找个 codepen 之类的贴下代码
    particlec
        12
    particlec  
    OP
       131 天前
    嗯,slice 确实要改成 includes ,主要是那个引用问题还不是很理解
    fengfuliu
        13
    fengfuliu  
       131 天前
    @particlec 问题就是你调用了 slice 导致的 slice 返回被裁减过的数组 因为是浅拷贝 影响到了 temporaryArr 吧
    sweetcola
        14
    sweetcola  
       131 天前
    slice 返回的是数组,数组 !== -1 那不是全部 true 吗...
    particlec
        15
    particlec  
    OP
       131 天前
    我打印了一下,发现原数组 temporaryArr 确实没有改变,就是 setSelectProductKey(temporaryArr);为啥没指向原数组
    sweetcola
        16
    sweetcola  
       131 天前
    @particlec 你用了 Spread 语法([...productKeyArr]),temporaryArr 就已经是一个新的数组了,不会指向原数组。
    particlec
        17
    particlec  
    OP
       131 天前
    不是 slice 的问题,换成 includes 也会出现同样的问题,应该跟 setSelectProductKey 有关
    particlec
        18
    particlec  
    OP
       131 天前
    @shabbyin “老数组你没有保存其堆地址的话 就再也访问不到了” 请教 老数组为啥访问不到,setSelectProductKey 为什么会指向新数组呢
    disk
        19
    disk  
       131 天前
    代码不全,看不出更多东西,建议自己跑个 debug 看下
    zhaomeicheng
        20
    zhaomeicheng  
       131 天前
    主题支持 Markdown 格式的,建议代码别直接贴,看不清楚...
    stillsilly
        21
    stillsilly  
       131 天前
    filter 改不改变原数组,要看你代码的写法。
    一般正常的用法是,返回一个新数组,不改变原数组。
    但是如果你在函数里写了有副作用的语句,比如 item.name = item.name + 111 、用了有副作用的 api push pop shift unshift reverse sort splice 之类的,那原数组当然改变了。
    filter 只是做一次循环迭代而已,跟 for 循环 forEach 循环 map 类似,你在 for 循环里也可以只做读操作,那就没有改原数组。也可以有写的操作,就改了原数组……
    stillsilly
        23
    stillsilly  
       131 天前
    temporaryArr.filter(obj => obj.slice(key) !== -1)
    这一句没有改原数组,slice 没有副作用


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

    这种写法不好,codereview 要被骂死的
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1154 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 23:55 · PVG 07:55 · LAX 16:55 · JFK 19:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.