Map over an object and change one properties value using native JS

后端 未结 6 1433
生来不讨喜
生来不讨喜 2021-02-06 22:50

I want to be able to return a result set of data and just change the formatting of the date field to something more readable leaving all the other data intact. I would prefer t

相关标签:
6条回答
  • 2021-02-06 23:17

    The issue here is that you're returning the array from the callback of the then function, which doesn't do anything. You want to pass the callback into the then function like so:

    function doSomething(tasks) {
      let results = tasks.map(task => task.start_date = task.start_date.format("YYYY-MM-DD"));
      return results;
    }
    
    function getAllTasks(callBack) {
      models.gantt_tasks.findAll()
      .then(callback)
      .catch(function(e) {
        console.error(e);
        return e;
      });
    }
    
    var results = getAllTasks(doSomething);
    
    0 讨论(0)
  • 2021-02-06 23:20

    you can make a generic function which take array of objects and return array with modified-props objects using map() and Object.assign().

    const users = [
        { name: 'Jhon', logged: 'Tue Feb 04 2020 14:16:10 GMT+0200 (Eastern European Standard Time)'  },
        { name: 'Doe', logged: 'Tue Feb 04 2020 14:20:10 GMT+0200 (Eastern European Standard Time)'  }
    ];
    
    
    const handleDates = (list, prop) => {
        return list.map(item => {
          const obj = Object.assign({}, item);
          obj[prop] = new Date(obj[prop]).toLocaleDateString();
          return obj;
        });
    }
    
    console.log(users)
    console.log(handleDates(users, 'logged'))

    0 讨论(0)
  • 2021-02-06 23:24

    .map() isn't the usual way to modify properties an existing array of objects. You can do that, but it's not what .map() is normally used for. Instead, it's a way to create a new array. A .map() callback returns a value, and those returned values get pushed into a new array, which .map() finally returns.

    Your .map() callback is implicitly returning task.start_date after assigning the formatted date into it. This means you're creating an array of formatted dates only, without the rest of the original task objects. If you wanted to use .map() here it would need to return task after making the assignment to task.start_date.

    But instead you may want to use .forEach() in your .then() callback. This is the method made for this job: it simply iterates over the array and lets you modify each element in place:

    tasks.forEach( task => task.start_date = task.start_date.format("YYYY-MM-DD") );
    return tasks;
    

    Also, as Dustin mentioned, returning a value from .then() may not do what you want here. The safest bet would be to do something with tasks right there, or to call another function and pass tasks as an argument. (I'm a little rusty on promises, though...)

    0 讨论(0)
  • 2021-02-06 23:24

    You can use Object.assign(target, ...sources) (here) of which you want to change only one value by keeping other values intact.

    For example:

    const object1 = {
     a: 1,
     b: 2,
     c: 3
    };
    

    Now suppose you want to change the value of b to 22, you can do this by:

    const object2 = Object.assign({}, object1, {b: 22});
    
    console.log(object1);  // { a: 1, b: 2, c: 3 } 
    console.log(object2);  // { a: 1, b: 22, c: 3 } 
    

    Notice, this does not change the value of object1, it creates a new empty object as defined in the first parameter of Object.assign() and it adds further parameters to the empty object, and if it encounters the same key again then it updates the value of the key.

    In this way you can change one or even multiple values of an Object.

    A BETTER WAY

    Airbnb's JavaScript Style Guide() {} says that:

    Prefer the object spread operator over Object.assign to shallow-copy objects.

    // very bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign(original, { c: 3 }); // this mutates 
    `original` ಠ_ಠ
    delete copy.a; // so does this
    
    // bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, 
    b: 2, c: 3 }
    
    // good
    const original = { a: 1, b: 2 };
    const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
    

    You can see the full documentation here

    0 讨论(0)
  • 2021-02-06 23:24

    Both ways worked for me. I think for testing I will use the forEach() until I need to duplicate it and then I will create the separate function.

    This is what I ended up with.

    let moment = require('moment');
    
    // Get all the Tasks
    function getAllTasks() {
     return models.gantt_tasks.findAll()
     .then(function(tasks) {
       tasks.forEach( task => task.start_date = moment(task.start_date).format("YYYY-MM-DD"));
       return tasks;
     })
     .catch(function(e) {
       console.error(e);
       return e;
     });
    }
    
    router.get('/data', (req, res) =>
     getAllTasks()
      .then((tasks) => res.json({ data: tasks }))
    )
    

    I ended up needing the Moment library to convert my dates as Sequelize wasn't let me easily manipulate the dates.

    0 讨论(0)
  • 2021-02-06 23:34

    You stay focused on simplicity of arrow functions. You can use Brackets {} and return the task object after change start_date. See:

    //Get all the Tasks
    function getAllTasks() {
      return models.gantt_tasks.findAll()
      .then(tasks => {
    
        let results = tasks.map(task => {
          task.start_date = task.start_date.format("YYYY-MM-DD");
          return task;
        });
        return results;
      })
      .catch(e => {
        console.error(e);
        return e;
      });
    }
    
    

    Nothing block you from use brackets and return on arrow functions.

    0 讨论(0)
提交回复
热议问题