I want to merge the properties/values of an object with a class instance. (I'm not sure what the correct terminology is in JS, but the example should clarify)
My attempts were with the spread syntax. See below.
I have a File-instance:
const files = listOfFilesFromDragNdrop();
let file = files[0];
console.log(file)
Outputs something like:
File(2398)
lastModified: 1530519711960
lastModifiedDate: Mon Jul 02 2018 10:21:51 GMT+0200
name: "my_file.txt"
preview: "blob:http://localhost:8080/6157f5d5-925a-4e5d-a466-24576ba1bf7c"
size: 2398
type: "text/plain"
webkitRelativePath: ""
After this is added, I use FileReader.readAsText() to obtain the contents, and wrap it in an object like:
contentObject = getFileContentFromFile()
console.log(contentObject)
Will output something like:
{
preview: "blob:http://localhost:8080/6157f5d5-925a-4e5d-a466-24576ba1bf7c",
content: "Lorem ipsum some text here."
}
I would like to end up with a merged object like:
{
// "preview" is the key used to map files and content
preview: "blob:http://localhost:8080/6157f5d5-925a-4e5d-a466-24576ba1bf7c",
// "text" is the new field with the content from contentObject
text: "Lorem ipsum some text here."
// The other fields are from the File instance
name: "my_file.txt",
size: 2398,
type: "text/plain",
lastModified: 1530519711960,
// ...
}
const mergedObject = {
...file,
text: contentObject.content
}
and similarily (aware that text
key would become content
) I tried
const mergedObject = {
...file,
...contentObject
}
But, Then I only get the contentObject
fields, i.e. the mergedObject
is similar to contentObject
. Interestingly, if I do
const mergedObject = {
...file
}
the mergedObject is a File instance. I assume that the spread operator does not work for class instances in the same way as it does for objects? How can I achieve a merged object?
FileReader
is implemented in a redux middleware and dispatches a new action with the { preview: '1234..ef', text: 'Lorem ipsum'}
object as payload after it has completed the read.preview
-field, and want to return the merged object in a "files"-reducer with something like: return files.map(file => file.preview !== payload.preview? file: {...file, text: payload.content}
JavaScript Merge Objects To merge objects into a new one that has all properties of the merged objects, you have two options: Use a spread operator ( ... ) Use the Object. assign() method.
The easiest way to merge two objects in JavaScript is with the ES6 spread syntax / operator ( ... ). All you have to do is insert one object into another object along with the spread syntax and any object you use the spread syntax on will be merged into the parent object.
You should use "Object. There's no need to reinvent the wheel for such a simple use case of shallow merging. The Object. assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
To merge a class instance and an object, in ES6, you can use Object.assign() to merge all the properties in object and maintain the original prototype for class instance. Spread operator only merge all the properties but not prototypes.
In you case, try:
const mergedObject = Object.assign(file, contentObject)
Remember in this case your original file object will be changed.
You may just have to do something like this...
const mergedObject = {
lastModified: file.lastModified,
lastModifiedDate: file.lastModifiedDate,
name: file.name,
size: file.size,
type: file.type,
webkitRelativePath: file.webkitRelativePath,
text: contentObject.content,
preview: contentObject.preview,
}
You could write a utility function to pull the pseudo properties from the file instance:
// Error is a like File with a pseudo property named message
let error = new Error('my error message')
error.status = 404;
const pick = (objectLike, properties) =>
properties.reduce(
(acc, key) => {
acc[key] = objectLike[key];
return acc;
},
{}
);
const contentObject = {
content: 'content text',
preview: 'http://url.io',
};
const mergedObject = {
...pick(error, Object.getOwnPropertyNames(error)),
...contentObject,
}
console.log(JSON.stringify(mergedObject));
Lodash has a pick function you could use for this.
Spread syntax like loops iterates over enumerable properties. And as you can see the code below shows that name
property of a File object is not enumerable. So the only way to get those properties is one by one.
document.querySelector('input').addEventListener('change', e => {
const file = e.target.files[0];
console.log(file.propertyIsEnumerable('name'));
});
<input type="file">
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With