【问题标题】:Iterating objects in es6 and returning new object在 es6 中迭代对象并返回新对象
【发布时间】:2016-04-22 01:14:34
【问题描述】:

使用 es6 javascript 可以迭代一个对象并返回一个新对象。例如:

const people = {
    'Sally': {
        age: 22,
        sex: 'female',
    },
    'John': {
        age: 64,
        sex: 'male',
    },
    'Sam': {
        age: 12,
        sex: 'female',
    },      
};

const ages = people.someEs6IteratingObjectFunction((index, person) => {
    return { Object.keys(people)[index]: person.age };
});

console.log(ages); // { 'Sally': 22, 'John': 64, 'Sam': 12, }   

【问题讨论】:

    标签: javascript iterator ecmascript-6


    【解决方案1】:

    您可以使用数组原型的reduce 方法。它也适用于 es5。

    const people = {
        'Sally': {
            age: 22,
            sex: 'female',
        },
        'John': {
            age: 64,
            sex: 'male',
        },
        'Sam': {
            age: 12,
            sex: 'female',
        },      
    };
    
    let result = Object.keys(people).reduce(function(r, name) {
      return r[name] = people[name].age, r;
    }, {});
    
    document.write(['<pre>', JSON.stringify(result, 0, 3), '</pre>'].join(''));

    【讨论】:

    • 虽然你能解释一下序列运算符的作用。对于新手来说有点复杂。让我们详细介绍一下 stackoverflow。
    • 逗号运算符计算其每个操作数(从左到右)并返回最后一个操作数的值
    • 是的,理解 :-) 虽然它通常在 ESLint 中禁止这样做。这可能会令人困惑。也许有两个例子?
    • 在这种情况下,只需将此表达式分成两部分。 r[name] = people[name].age; return r;。我不知道这条规则:)
    • :-) 很酷,还有一条规则“不要返回赋值语句”.. AirBnB linting...
    【解决方案2】:

    如果您不太关心潜在性能,可以选择一个:

    const ages = people.reduce(
        (obj, name) => Object.assign(obj, {[name]: obj[name].age}), {});
    

    或许

    const ages = Object.entries(people).reduce(
        (obj, [name, info]) => Object.assign(obj, {[name]: info.age}), {});
    

    或者制作一个 ES6 Map 而不是使用 Object

    const ages = new Map(Object.entries(people).map(
        ([name, info]) => [name, info.age])))
    

    【讨论】:

    • 很遗憾,Object.entries 仍然不是标准的。
    • @Bergi 第 4 阶段,正式进入,等待官方 ES2016 规范发布!
    • @loganfsmyth:现在处于第 4 阶段意味着它将成为 ES2017 的一部分。
    • 糟糕,我错了!这么近。
    【解决方案3】:

    这是一种方法,我希望我能对此表示赞赏,它来自 Axel Rauschmayer 的博客,他在这里还有其他几篇令人惊叹的博客文章:http://www.2ality.com/2015/02/es6-iteration.html

    这是JSBin with the code below:

     function objectEntries(obj) {
            let index = 0;
            let propKeys = Reflect.ownKeys(obj);
            return {
                [Symbol.iterator]() {
                    return this;
                },
                next() {
                    if (index < propKeys.length) {
                        let key = propKeys[index];
                        index++;
                        return { value: [key, obj[key]] };
                    } else {
                        return { done: true };
                    }
                }
            };
        }
    
        let obj = { first: 'Jane', last: 'Doe' };
        for (let [key,value] of objectEntries(obj)) {
            console.log(`${key}: ${value}`);
        }
    

    如果您使用生成器,这会更容易:http://www.2ality.com/2015/03/es6-generators.html

    【讨论】:

      【解决方案4】:

      不幸的是,在 ES6 中没有 Array.map 等价的对象。

      也许您可以创建一个辅助函数来模仿这一点。它将遍历您的对象,使用该键的值调用每个键的回调,并用回调返回的任何值替换该值。比如:

      const objectMap = (obj, cb) => 
        Object.keys(obj).reduce((ppl, k) =>
          Object.assign(ppl, {
            [k]: cb(obj[k])
          }), {}
        );
      

      然后像这样使用它:

      const newPeople = objectMap(people, val => val.age);
      console.log(newPeople); // Object {Sally: 22, John: 64, Sam: 12}
      

      运行示例:

      const people = {
        'Sally': {
          age: 22,
          sex: 'female',
        },
        'John': {
          age: 64,
          sex: 'male',
        },
        'Sam': {
          age: 12,
          sex: 'female',
        },
      };
      
      const objectMap = (obj, cb) => 
        Object
        .keys(obj)
        .reduce(
          (ppl, k) =>
          Object.assign(ppl, {
            [k]: cb(obj[k])
          }), {}
        );
      
      const newPeople = objectMap(people, val => val.age);
      
      console.log('---- People ----');
      console.dir(people);
      
      console.log('---- New People ---- ');
      console.dir(newPeople);

      【讨论】:

        【解决方案5】:

        也许你可以使用for...of

         const people = { 'Sally': { age: 22, sex: 'female', }, 'John': { age: 64, sex: 'male', }, 'Sam': { age: 12, sex: 'female', },
        };
        
        const ages = {};
        for(let index of people) {
          ages[key] = people[key].age;
        }
        console.log(ages); // { 'Sally': 22, 'John': 64, 'Sam': 12, }
        

        【讨论】:

        • 标准对象不可迭代,因此 for..of 不起作用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 1970-01-01
        • 2011-07-23
        • 1970-01-01
        • 2015-09-06
        • 1970-01-01
        • 2020-08-29
        相关资源
        最近更新 更多