我正在尝试提高有关javascript中记忆的知识。我创建了一个记忆功能(我认为..)
我已经对项目进行了一系列更改(更改日志)。数组中的每个项目都包含对其进行编辑的reference-id(employeeId)。看起来像这样。
const changeLog = [
{
id: 1,
employeeId: 1,
field: 'someField',
oldValue: '0',
newValue: '100',
},
{
id: 2,
employeeId: 2,
field: 'anotherField',
oldValue: '20',
newValue: '100',
},
...
]
我还有一个包含每个员工的数组,看起来像这样:
const employees = [
{
name: 'Joel Abero',
id: 1
},
{
name: 'John Doe',
id: 2
},
{
name: 'Dear John',
id: 3
}
]
要找到进行更改的员工,我将其映射到changeLog中的每个项目上,并找到employeeId等于employees数组中的id的位置。这两个数组都包含500多个项目,我刚刚粘贴了片段。下面,我粘贴了我的备忘录助手。
1)如何执行测试以查看这两个中运行最快的一个?2)这是使用记忆的正确方法吗?3)使用记忆时有经验法则吗?还是应该尽可能多地使用它?
const employees = [
{
name: 'Joel Abero',
id: 1
},
{
name: 'John Doe',
id: 2
},
{
name: 'Dear John',
id: 3
}
]
const changeLog = [
{
id: 1,
employeeId: 1,
field: 'someField',
oldValue: '0',
newValue: '100',
},
{
id: 2,
employeeId: 2,
field: 'anotherField',
oldValue: '0',
newValue: '100',
},
{
id: 3,
employeeId: 3,
field: 'someField',
oldValue: '0',
newValue: '100',
},
{
id: 4,
employeeId: 3,
field: 'someField',
oldValue: '0',
newValue: '100',
},
{
id: 5,
employeeId: 3,
field: 'someField',
oldValue: '0',
newValue: '100',
}
]
function findEditedByEmployee (employeeId) {
return employees.find(({ id }) => id === employeeId)
}
function editedByWithMemoize () {
let employeesSavedInMemory = {}
return function(employeeId) {
if(employeeId in employeesSavedInMemory) {
console.log("from memory")
return employeesSavedInMemory[employeeId]
}
console.log("not from memory")
const findEditedBy = findEditedByEmployee(employeeId)
employeesSavedInMemory[findEditedBy.id] = {name: findEditedBy.name }
return findEditedBy
}
}
const memoizedEmployee = editedByWithMemoize();
// with memoization
const changeLogWithEmployeesMemoized = changeLog.map( log => {
const employeeName = memoizedEmployee(log.employeeId);
return {
...log,
employeeName: employeeName.name
}
})
// without memoization
const changeLogWithEmployees = changeLog.map( log => {
const editedBy = findEditedByEmployee(log.employeeId);
return {
...log,
employeeName: editedBy.name
}
})
console.log('memoized', changeLogWithEmployeesMemoized)
console.log('not memoized', changeLogWithEmployees)
我会事先创建一个Map
并从地图上获取该对象以进行更新。
如果Map
不包含所需的map
,则创建一个新对象并将其添加到id
和employees
中。
map
const
employees = [{ name: 'Joel Abero', id: 1 }, { name: 'John Doe', id: 2 }, { name: 'Dear John', id: 3 }],
changeLog = [{ id: 1, employeeId: 1, field: 'someField', oldValue: '0', newValue: '100' }, { id: 2, employeeId: 2, field: 'anotherField', oldValue: '20', newValue: '100' }],
map = employees.reduce((map, o) => map.set(o.id, o), new Map);
for (const { id, field, newValue } of changeLog) {
let object = map.get(id);
if (object) {
object[field] = newValue;
} else {
let temp = { id, [field]: newValue };
employees.push(temp)
map.set(id, temp);
}
}
console.log(employees);
我将尝试回答您的每个问题:
1)如何执行测试以查看这两个中运行最快的一个?
最好的方法只是简单的for循环。
2)这是使用记忆的正确方法吗?
我不确定您的意思,但是可以将其视为短期缓存。如果您的备忘录调用包含一个API请求,那么这对于不更改数据非常有用,可以节省大量时间,但是,另一方面,如果数据在短时间内可能发生更改,那么备忘录可能会很糟糕想法,这意味着它很快就会过时。
如果您对此函数进行许多调用,则它可能会消耗内存,具体取决于返回数据的大小,但这取决于实现,而不是“适当的方法”。
3)使用备忘录时有经验法则吗?还是应该尽可能多地使用它?
如果您开始使用记忆功能,则应尽可能在任何地方使用它。但是,如前所述,它可以根据返回数据迅速耗尽内存。如果您只调用几次甚至一次调用一个函数,则备忘录几乎没有好处。
关于记忆的最后一点是,如果数据已经是客户端,则建议使用像.as-console-wrapper { max-height: 100% !important; top: 0; }
这样的映射绝对是一种更好,更有效的方法。它无需循环每次来查找对象,而是循环一次以将数组转换为对象(或映射),从而使您可以在O(1)时间内访问数据。
总而言之,记忆是一个很棒的工具-尤其是在发出API请求时,
((我还在为此答案添加更多内容)