Javascript 使用原生 JS 映射对象并更改一个属性值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39462733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Map over an object and change one properties value using native JS
提问by jeff randall
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 to do this without a third party library.
我希望能够返回数据的结果集,只需将日期字段的格式更改为更具可读性的内容,而让所有其他数据保持不变。我宁愿在没有第三方库的情况下做到这一点。
Here is what I have so far:
这是我到目前为止所拥有的:
//Get all the Tasks
function getAllTasks() {
return models.gantt_tasks.findAll()
.then(function(tasks){
let results = tasks.map(task => task.start_date = task.start_date.format("YYYY-MM-DD"));
return results;
})
.catch(function(e) {
console.error(e);
return e;
});
}
And I would like for the Map to complete before it returns the data.
我希望 Map 在返回数据之前完成。
回答by Michael Geary
.map()
isn't the usual way to modify properties an existing array of objects. You cando that, but it's not what .map()
is normally used for. Instead, it's a way to create a newarray. A .map()
callback returns a value, and those returned values get pushed into a new array, which .map()
finally returns.
.map()
不是修改现有对象数组的属性的常用方法。你可以这样做,但这不是.map()
通常的用途。相反,它是一种创建新数组的方法。一个.map()
回调函数返回一个值,这些返回的值将被推到一个新的数组,其.map()
最终的回报。
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
.
在将格式化日期分配给.map()
回调task.start_date
后,您的回调将隐式返回。这意味着您只创建了一个格式化日期数组,而没有其他原始task
对象。如果您想在.map()
此处使用,则需要task
在对 进行分配后返回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:
但是,您可能希望.forEach()
在.then()
回调中使用。这是为这项工作制定的方法:它只是遍历数组并让您就地修改每个元素:
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...)
此外,正如 Dustin 所提到的,从.then()
这里返回一个值可能不会做你想要的。最安全的选择是在那里做一些事情tasks
,或者调用另一个函数并tasks
作为参数传递。(不过,我对承诺有点生疏……)
回答by Amit Dimri
You can use Object.assign(target, ...sources)
(here) of which you want to change only one value by keeping other values intact.
您可以使用Object.assign(target, ...sources)
( here) 通过保持其他值不变而仅更改一个值。
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:
现在假设你想改变的值b
来22
,你可以这样做:
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.
请注意,这不会更改 object1 的值,它会创建一个新的空对象,如第一个参数中定义的那样Object.assign()
,并向空对象添加更多参数,如果再次遇到相同的键,则更新键的值.
In this way you can change one or even multiple values of an Object.
通过这种方式,您可以更改一个对象的一个甚至多个值。
Airbnb's JavaScript Style Guide() {}
says that:
Airbnb's JavaScript Style Guide() {}
说:
Prefer the object spread operator over
Object.assign
to shallow-copy objects.
优先使用对象扩展运算符而不是
Object.assign
浅拷贝对象。
// 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
您可以在此处查看完整文档
回答by Adson Cicilioti
You stay focused on simplicity of arrow functions. You can use Brackets {}
and return
the task
object after change start_date
. See:
您始终专注于箭头函数的简单性。您可以使用 Brackets{}
和更改后return
的task
对象start_date
。看:
//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.
没有什么能阻止您使用括号和返回箭头函数。
回答by Muhammed Moussa
you can make a generic function which take array of objects and return array with modified-props objects using map()
and Object.assign()
.
您可以创建一个通用函数,该函数采用对象数组并使用map()
和返回带有修改道具对象的数组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'))
回答by nikjohn
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:
这里的问题是你从then
函数的回调中返回数组,它什么也不做。您想将回调传递给 then 函数,如下所示:
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);
回答by jeff randall
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.
两种方式都对我有用。我认为为了测试我会使用forEach()
直到我需要复制它然后我将创建单独的函数。
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.
我最终需要 Moment 库来转换我的日期,因为 Sequelize 不允许我轻松操纵日期。