I'm sure many of you are familiar with the Object
data type. Many of the data types that we use in everyday programming inherit from this type, like objects and arrays. But did you know about these seven methods and what they're capable of?
Let's dive right in.
Object.assign()
Ever want some properties to carry over from one object to another? This method provides that functionality!
const obj = {
a: 0,
b: 1,
c: 2
};
const ex = {
c: 3,
d: 4,
e: 5
};
Object.assign(obj, ex);
console.log(Object.entries(obj)); // [["a", 0], ["b", 1], ["c", 3], ["d", 4], ["e", 5]]
This method takes the first argument (the target) and adds the properties from the second (or more, all together are called the sources) to it, overwriting any properties from the original object that have the same name.
Let's look at an example that has more than one source.
const obj = {
a: 0,
b: 1,
c: 2
};
const arr = [
{ d: 3 },
{ e: 4, f: 5 }
]
Object.assign(obj, ...arr);
console.log(Object.entries(obj)); // [["a", 0], ["b", 1], ["c", 2], ["d", 3], ["e", 4], ["f", 5]]
Object.freeze()
When we want to keep a variable from being altered, we use a constant (defined with const
as the variable declaration). However, this sometimes is ineffective - especially when we're dealing with arrays or objects where properties can still be overwritten. This is where Object.freeze()
comes in.
const obj = {
a: 0,
b: 1,
c: 2
};
Object.freeze(obj);
obj.d = 3;
console.log(Object.entries(obj)); // [["a", 0], ["b", 1], ["c", 2]]
Note that this is in non-strict mode. When in strict mode, an error will be thrown if an attempt is made to modify the frozen object.
It works with arrays too.
const arr = ["a", "b", "c"];
Object.freeze(arr);
arr[3] = "d";
console.log(arr); // ["a", "b", "c"]
Hence we can create fully constant variables with the power of freezing.
Object.isFrozen()
Don't know whether or not an object is frozen? Check using this method!
const obj = {
a: 0,
b: 1,
c: 2
};
console.log(Object.isFrozen(obj)); // false
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true
You might be wondering how you unfreeze an object. Short answer - you can't.
The best workaround to reusing a frozen object is by creating a copy that isn't frozen. That's about as far as you can get.
However, there are a few fixes like Object.seal()
and Object.preventExtensions()
. These methods allow some mutation of the frozen object, but it will never respond quite the same way. If you're freezing an object, plan for it to stay frozen - it's a pretty big security risk otherwise.
Object.entries()
This method is pretty useful as it allows us to create a full list of keys and values. It's also useful when working with data structures like Map
- it makes conversion to and from the structure easy. Let's take a look at how it works.
const obj = {
a: 0,
b: 1,
c: 2
};
console.log(Object.entries(obj)); // [["a", 0], ["b", 1], ["c", 2]]
As you can see, it's returning an array. Not just any array though, it's an array that's full of other arrays - each representing a key-value pair.
And yes, it works with arrays too.
const arr = ["a", "b", "c"];
console.log(Object.entries(arr)); // [["0", "a"], ["1", "b"], ["2", "c"]]
Why is this useful? For one, it provides a clean way to iterate through lists.
const obj = {
a: 0,
b: 1,
c: 2
};
let objList = Object.entries(obj);
for (let i = 0; i < objList.length; i++) {
console.log(`${objList[i][0]}: ${objList[i][1]}`)
}
// "a: 0"
// "b: 1"
// "c: 2"
Apart from that, it's helpful when used to convert an object to a map.
const obj = {
a: 0,
b: 1,
c: 2
};
const map = new Map(Object.entries(obj));
console.log(map.size); // 3
console.log(map.get("a")); // 0
Object.fromEntries()
This is Object.entries()
working backwards. It takes an array of arrays representing key-value pairs and creates an object. Let's start with the map we just created to demonstrate the difference.
const obj = {
a: 0,
b: 1,
c: 2
};
const map = new Map(Object.entries(obj));
const newObj = Object.fromEntries(map);
console.log(Object.entries(obj)); // [["a", 0], ["b", 1], ["c", 2]]
console.log(Object.entries(newObj)); // [["a", 0], ["b", 1], ["c", 2]]
Even though we can't check for equality without working through some long-winded process, we can print out the entries and see that they are in fact the same.
You don't have to work from a map though, you can easily create a custom array and plug it in to create the same object.
const arr = [
["a", 0],
["b", 1],
["c", 2]
];
console.log(Object.fromEntries(arr)); // { a: 0, b: 1, c: 2 }
Object.keys()
This method returns an array of all keys that are defined by a given object. Consider the following object, which has three key-value pairs.
const obj = {
a: 0,
b: 1,
c: 2
};
console.log(Object.keys(obj)); // ["a", "b", "c"]
You can also pass an array as an argument with some interesting results.
const arr = ["a", "b", "c"];
console.log(Object.keys(arr)); // ["0", "1", "2"]
This behavior is due to the fact that arrays are indexed with numbers, so in a way they're like objects that have numbers connected to values. Heck, we could make an object that behaves exactly similar to this array that produces exactly the same result.
const arr = ["a", "b", "c"];
console.log(Object.keys(arr)); // ["0", "1", "2"]
const obj = {
"0": "a",
"1": "b",
"2": "c"
};
console.log(Object.keys(obj)); // ["0", "1", "2"]
One of the possible uses of this method is to iterate through an object - once we know how many keys an object has, we can go through each one and print out it and its respective value.
const obj = {
a: 0,
b: 1,
c: 2
};
let keys = Object.keys(obj);
console.log(keys); // ["a", "b", "c"]
for (let i = 0; i < keys.length; i++) {
console.log(`${keys[i]}: ${obj[keys[i]]}`);
}
// "a: 0"
// "b: 1"
// "c: 2"
Object.values()
This method functions in largely the same way as Object.keys()
- it takes something like an object and returns an array of the values associated with each key, not the keys associated with each value.
We can take the same code that we used earlier and substitute the new method in place of the old one to see what it returns.
const obj = {
a: 0,
b: 1,
c: 2
};
console.log(Object.values(obj)); // [0, 1, 2]
We can pass an array to the method, but this functions exactly the same as simply calling the array itself because all it's doing is returning an array of the elements.
const arr = ["a", "b", "c"];
console.log(Object.values(arr)); // ["a", "b", "c"]
console.log(arr); // ["a", "b", "c"]
I'm sure you can think of more than one use case for this method as well (iterating through an object, finding the size of an object, etc.
I've thought of one that I'll write here - I want to find the size of any object with a handy method that I'm taking from the Set
data structure in JS - Object.size
. My problem is that this method doesn't exist - yet! Let's create it by using our newfound knowledge.
const obj = {
a: 0,
b: 1,
c: 2
};
Object.prototype.size = function() {
return Object.values(this).length;
};
console.log(obj.size()); // 3
obj.d = 3;
console.log(obj.size()); // 4
That's just fantastic, although you should keep in mind that adding methods like this to a larger class like Object
is generally frowned upon. We can make our code better by just creating a function that we pass an object to.
const getObjectSize = function(obj) {
return Object.values(obj).length;
};
Don't forget ES6 syntax!
const getObjectSize = obj => Object.values(obj.length);
Fin.
Hope you enjoyed!
Don't forget to drop a like and a follow if you like my posts. Later :)
Top comments (5)
Cool post!
In a past project I decided to use the
freeze()
method, notice that the freeze method only works at one level (so it's not deep-frozen), this means that if you freeze an object and that object has a property containing another object, the inside object won't be affected by the cold (🥁 ba dum tss!).P.S.
Object.seal()
can be useful to create custom parameters with limited properties...For example, you could define a variable containing an object with the default values, then you
seal()
your object with the default values, and then youassign()
the custom values passed to it (like the ones passed through a function argument), and ta da! Now you can avoid other programmers to inject other properties in parameters where you only want to limit the custom properties to the ones you specified.Hope this helps!
Some really helpful information on the
freeze()
method, thanks Rodrigo!That's really interesting, but it makes sense. Turns out freeze just acts like an extension of the
const
declaration - when it's used, it locks everything on the main level. Other objects and arrays on deeper levels are still accessible.Yeah, you can get around it to some extent with
seal()
(great example, by the way!). The thing that really hit me was that anunfreeze()
doesn't exist, but it makes sense given vulnerability risks.Thanks again for making this post better with your contributions! I appreciate your feedback :)
Yeah, I did my research there too, your option there is to make a copy of the frozen object with another variable, and then you can modify that variable but not the originally frozen object.
Glad to help 😉
out of all of the great methods, i must question your reasonin' as to why you decided to choose
Object.isFrozen
overObject.create
orObject.defineProperty
as both have much more applications an'Object.isFrozen
should truly have been left as a footnote in theObject.freeze
section.No specific reasoning was involved besides from the fact that I had just learned about it and felt like sharing! This was a method that - as you mentioned - could probably have just been lumped in with
Object.freeze
, however, I chose to include it as a separate method. I'm not gonna say my choice was wrong, but I can certainly see where you're coming from and that the point of view is logical.