The task is to implement a function to mimic the Immutability helper function.
The boilerplate code
function update(data, command) {
// your code here
}
The immutability helper function applies changes to data without mutating the original value by interpreting a command that describes what to change.
If the command is $set, it means to ignore the old data and replace it completely. As soon as $set is found, it is returned immediately
if ('$set' in command) {
return command.$set;
}
Clone the original data to ensure it isn't mutated
const result = Array.isArray(data) ? data.slice() : { ...data };
If the command is $apply, it means a function is run on the current value, and a new value is returned. It must be a function, or it throws an error
if ('$apply' in command) {
if (typeof command.$apply !== 'function') {
throw new Error('$apply must be a function');
}
return command.$apply(data);
}
If the command is $merge, it means shallow-merging of new properties can be done on the data. The data must be an object
if ('$merge' in command) {
if (typeof data !== 'object' || data === null || Array.isArray(data)) {
throw new Error('$merge can only be used on objects');
}
return { ...data, ...command.$merge };
}
If the command is $push, it means items can be appended to the end of an array. Concat is used to avoid mutating the original array.
if ('$push' in command) {
return result.concat(command.$push);
}
If the command is $unshift, it means items can be added at the beginning of an array.
if ('$unshift' in command) {
return { ...result, ...command.$unshift };
}
If the command is $splice, it means the array can be modified.
if ('$splice' in command) {
const copy = result.slice();
command.$splice.forEach(args => {
copy.splice(...args);
});
return copy;
}
If there is no specific command, walk through each key in command and recursively apply update to the nested data
Object.keys(command).forEach(key => {
result[key] = update(data[key], command[key]);
});
Return the updated copy
return result;
The final code
function update(data, command) {
// your code here
if('$set' in command) {
return command.$set;
}
const result = Array.isArray(data) ? data.slice() : {...data};
if('$apply' in command) {
if(typeof command.$apply !== 'function') {
throw new Error('$apply must be a function')
}
return command.$apply(data);
}
if('$merge' in command) {
if(typeof data !== 'object' || data === null || Array.isArray(data)) {
throw new Error('$merge can only be used on objects')
}
return {...data, ...command.$merge}
}
if('$push' in command) {
return result.concat(command.$push);
}
if('$unshift' in command) {
return{...result, ...command.$unshift};
}
if('$plice' in command) {
const copy = result.slice();
command.$splice.forEach(args => {
copy.splice(...args);
})
return copy;
}
Object.keys(command).forEach(key => {
result[key] = update(data[key], command[key]);
})
return result;
}
That's all folks!
Top comments (0)