【问题标题】:Modify object property in an array of objects修改对象数组中的对象属性
【发布时间】:2013-05-17 12:12:36
【问题描述】:
var foo = [{ bar: 1, baz: [1,2,3] }, { bar: 2, baz: [4,5,6] }];

var filtered = $.grep(foo, function(v){
    return v.bar === 1;
});

console.log(filtered);

http://jsfiddle.net/98EsQ/

有什么方法可以在不创建新数组和/或对象的情况下修改某个对象属性(例如我在上面过滤掉的那个)?

想要的结果:[{ bar: 1, baz: [11,22,33] }, { bar: 2, baz: [4,5,6] }]

【问题讨论】:

  • @squint 我正在寻找一种方法,它允许我“指向”某个对象并让我改变它(在 ES 或 jQuery 中)。但我想我必须用 foreach 手动完成 :)

标签: javascript jquery


【解决方案1】:

.mapspread (...) 运算符

var result = foo.map(el => el.bar == 1 ? {...el, baz: [11,22,33]} : el);

【讨论】:

  • 我无法根据 prev 值更新“baz”,只能完全更改 prop 值。
【解决方案2】:

当然,只要改变它:

用 jQuery 的$.each:

$.each(foo, function() {
    if (this.bar === 1) {
        this.baz[0] = 11;
        this.baz[1] = 22;
        this.baz[2] = 33;
        // Or: `this.baz = [11, 22, 33];`
    }
});

使用 ES5 的 forEach:

foo.forEach(function(obj) {
    if (obj.bar === 1) {
        obj.baz[0] = 11;
        obj.baz[1] = 22;
        obj.baz[2] = 33;
        // Or: `obj.baz = [11, 22, 33];`
    }
});

...或者你有other looping options in this other SO answer

【讨论】:

    【解决方案3】:

    您可以使用find 并更改其属性。

    let foo = [{ bar: 1, baz: [1,2,3] }, { bar: 2, baz: [4,5,6] }];
    
    let obj = foo.find(f=>f.bar==1);
    if(obj)
      obj.baz=[2,3,4];
    console.log(foo);

    【讨论】:

    • 这只有在你知道你总会有一个匹配项时才有用
    • @AdiG 是的。如果您正在查看多个,最好使用map,例如this answer
    【解决方案4】:

    没有 jQuery 和向后兼容性

    for (var i = 0; i < foo.length; i++) {
        if (foo[i].bar === 1) {
            foo[i].baz = [11,12,13];
        }
    }
    

    【讨论】:

      【解决方案5】:

      我们也可以通过Array的map函数来实现:

       foo.map((obj) => {
         if(obj.bar == 1){
           obj.baz[0] = 11;
           obj.baz[1] = 22;
           obj.baz[2] = 33;
         }
       })
      

      【讨论】:

        【解决方案6】:
            const objArr = [
                {prop1: 'value1', prop2: 'value11'},
                {prop1: 'value2', prop2: 'value22'},
                {prop1: 'value3', prop2: 'option33'},
                {prop1: 'value4', prop2: 'option44'}
            ]
        
            const newObjArr = objArr.map(obj => {
                    if (['value1', 'value2'].includes(obj.prop1)) {
                        return {...obj, prop1: 'newValue'}
                    }
                    return obj
                }
            )
            
            // const responseGotten = [
            //     { prop1: 'newValue', prop2: 'value11' },
            //     { prop1: 'newValue', prop2: 'value22' },
            //     { prop1: 'value3', prop2: 'option33' },
            //     { prop1: 'value4', prop2: 'option44' }
            // ]
        

        【讨论】:

        • 出色的工作人员。你简化了一个很好的逻辑。谢谢
        【解决方案7】:
        $.each(foo,function(index,value)
        {
            if(this.bar==1)
            {
        this.baz[0] = 11;
                this.baz[1] = 22;
                this.baz[2] = 33;
            }
        
        });
        

        但是 for 循环比 $.each 快,所以你可以尝试使用

        for(var i=0; i <foo.length; i++)
        {
        
        if(foo[i].bar==1)
        {
        //change the code
        }
        }
        

        【讨论】:

          【解决方案8】:

          但在选择任何上述技术之前,请记住与每种方法相关的性能挑战。

          Object iterate For-In, average: ~240 microseconds.
          
          Object iterate Keys For Each, average: ~294 microseconds.
          
          Object iterate Entries For-Of, average: ~535 microseconds.
          

          参考 - 3 JavaScript Performance Mistakes You Should Stop Doing

          【讨论】:

            【解决方案9】:

            你可以利用javascript的过滤功能。

            obj = [
                {inActive:false, id:1},
                {inActive:false, id:2},
                {inActive:false, id: 3}
            ];
            let nObj = obj.filter(ele => {
                ele.inActive = true;
                return ele;
            });
            
            console.log(nObj);

            【讨论】:

            • 映射在语义上不会更正确吗?您并没有真正过滤任何东西,因为您的意图始终是返回每个元素。此外,您也没有真正改变对象,只是创建一个已更改的副本。我认为 OP 明确表示没有新对象。
            【解决方案10】:

            你可以使用简单的for循环来修改数组

            var foo = [{ bar: 1, baz: [1,2,3] }, { bar: 2, baz: [4,5,6] }];
            for(i = 0;i < foo.length;i++){
              //Here your confition for which item you went to edit
            	if(foo[i].bar == 1){
                //Here you logic for update property
            		foo[i].baz= [1,11,22]
            	}
            }
            console.log(foo);

            【讨论】:

              【解决方案11】:

              你可以到处玩:

              const tasks = [ { id: 1, done: false }, { id: 2, done: false } ]
              const completed_task = { id: 1, done: true }
              
              const markCompleted = (tasks, task) => {
                const index = tasks.findIndex(t => t.id === task.id);
                tasks.splice(index, 1);
                tasks.push(task);
                return tasks;
              }
              
              console.log(tasks)
              console.log(markCompleted(tasks, completed_task))

              编辑

              避免索引变化:

              const markCompleted = (tasks, task) => {
                    const index = tasks.findIndex(t => t.id === task.id);
                    tasks[index] = task;
                    return tasks;
                  }
              

              【讨论】:

                猜你喜欢
                • 2021-09-27
                • 1970-01-01
                • 2019-08-22
                • 2021-05-31
                • 2021-10-27
                • 2011-03-02
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多