In JavaScript, the Object
constructor lets us create object wrapper with the given values. It will create an empty object if null
or undefined
is passed into the Object constructor. If the value passed into the constructor is an object already then, it will return the object.
The Object
constructor has 2 properties. It has a length
property that is always 1, and like all other objects, the Object
constructor has a prototype to get all the property additions to the type Object.
The Object
constructor has many useful methods that can be used without constructor a new object. Part 1 of this list is below:
Object.assign()
The Object.assign()
method makes a shallow copy of an object. The first parameter is a target object that you copy the object to, and the second parameter accepts an object that you want to copy. Note that if the source and target objects have the same properties, the source object’s property value to overwrite the one in the target object. For example, we can write:
const target = { a: 1, b: 2 };
const source = { b: 3, c: 4};
const newObj = Object.assign(target, source);
console.log(newObj)
If we run the code, we will get { a: 1, b: 3, c: 4}
. We can also copy arrays. For example, we can write:
const targetArr = [1,2];
const sourceArr = [2,3];
const newArr = Object.assign(targetArr, sourceArr);
console.log(newArr)
We get [2,3]
logged when we run the code above. For arrays, it will overwrite the whole target array with the source array.
Object.create()
The Object.create()
method creates a new object with the object you pass in as the prototype of the new object. For example, we can write:
const obj = { a: 1, b: 2, c: 3 };
const newObj = Object.create(obj);
console.log(newObj);
In the code above, when we log newObj
, it doesn’t have its own properties that weren’t inherited from obj
. This is because we only passed in the first argument to the constructor, which is the prototype for the object that’s returned. If we want to add properties that are available only in the returned object, we pass in an object with the property names as keys and the properties writable
, configurable
, enumerable
and value
as properties of the property name keys, which is called the property descriptor. For example, we can write:
const obj = {
a: 1,
b: 2,
c: 3
};
const childObj = {
a: {
writable: true,
configurable: true,
value: 'hello'
},
d: {
writable: true,
configurable: true,
value: 'hello'
}
}
const newObj = Object.create(obj, childObj);
console.log(newObj);
In the code above, writable
means that the property’s value can be changed. configurable
means the property descriptor may be changed and if the property can be deleted from the object. The enumerable
property means that the property shows up during enumeration of the properties with the for...in
loop, and value
is the value of the property.
If we want to create an object that has properties that can’t be changed, then we set writable
to false
, like in the following code:
const obj = {
a: 1,
b: 2,
c: 3
};
const childObj = {
a: {
writable: false,
configurable: true,
value: 'hello'
},
d: {
writable: true,
configurable: true,
value: 'hello'
}
}
const newObj = Object.create(obj, childObj);
newObj.a = 1;
newObj.d = 1;
console.log(newObj);
Notice that the assignment operator has no effect. If we have strict mode enabled, then a TyepError
will be thrown. We have {a: “hello”, d: 1}
logged in the console.log
. This means that writable
set to false
is working for the property a
and writable
value set to true
is working for the property d
.
If we pass in null
to the constructor, we get an empty object:
const nullObj = Object.create(null)
console.log(nullObj)
We will get an error ‘Object prototype may only be an Object or null: undefined’ is we pass in undefined
as the prototype of an object like in the code below:
const undefinedObj = Object.create(undefined);
console.log(undefinedObj)
Object.defineProperty()
The Object.defineProperty()
method defines a new property on an object. The first parameter is the object that you want to add the property to. The second parameter is the name of the property you want to add passed in as a string, and the last parameter is the property descriptor included in the Object.create()
method when we try to add properties to the returned object. The property descriptor should have the properties writable
, configurable
, enumerable
and value
as properties of the property name keys. The writable
means that the property’s value can be changed. configurable
means the property descriptor may be changed and if the property can be deleted from the object. The enumerable
property means that the property shows up during enumeration of the properties with the for...in
loop, and value
is the value of the property. For example, we can write:
let obj = {};
Object.defineProperty(obj, 'a', {
writable: false,
configurable: true,
value: 'hello'
})console.log(obj.a)
obj.a = 1;
console.log(obj.a)
As we can see, the property descriptor acts the same way as in Object.create()
. When writable
is false
, assignment to the property has no effect. If we have strict mode enabled, then a TyepError
will be thrown.
We can also define getters and setter function for properties called get
and set
respectively for a property:
let obj = {};
let value;Object.defineProperty(obj, 'a', {
get() {
return value;
},
set(a) {
value = a;
}
});console.log(obj.a)
obj.a = 1;
console.log(obj.a)
As we can see, in the code above, we defined the property a
for the object obj
with the get
and set
functions to get the value of the property and set the value respectively.
Accessor properties are set on the prototype if we defined it on the prototype, but value properties are set on the current object. If an object inherits non-writable properties, it will still be non-writable on the current object. For example, if we have:
let ObjClass = function() {};
ObjClass.prototype.a = 1;
Object.defineProperty(ObjClass.prototype, "b", {
writable: false,
value: 1
});
const obj = new ObjClass();
ObjClass.prototype.a = 3
obj.a = 2
ObjClass.prototype.b = 3
obj.b = 2
console.log(obj);
Then assigning to property b
is no effect. If we have strict mode enabled, then a TyepError
will be thrown.
Object.defineProperties()
The Object.defineProperties
method let us define more than one property on an object. The first parameter of the method is the object that you want to define the properties on, and the second object contains the property names as key and the corresponding property descriptors as values. The property descriptor should have the properties writable
, configurable
, enumerable
and value
as properties of the property name keys. The writable
means that the property’s value can be changed. configurable
means the property descriptor may be changed and if the property can be deleted from the object. The enumerable
property means that the property shows up during enumeration of the properties with the for...in
loop, and value
is the value of the property. For example, we can write:
let obj = {}
Object.defineProperties(obj, {
a: {
writable: true,
configurable: true,
value: 'hello'
},
d: {
writable: false,
configurable: true,
value: 'hello'
}
})
obj.a = 1;
obj.d = 1;
console.log(obj);
To add the a
and d
properties where a
‘s value can change and d
‘s value can’t. The console.log
will show {a: 1, d: “hello”}
since the value assignment to d
fails because the writable
property of property d
‘s descriptor is set to false
. We can also set configurable
to false
to prevent it from being deleted or having its property descriptor changed. For example, we can write:
let obj = {}
Object.defineProperties(obj, {
a: {
writable: true,
configurable: true,
value: 'hello'
},
d: {
writable: false,
configurable: false,
value: 'hello'
}
})
obj.a = 1;
delete obj.d;
console.log(obj);
If we run the code above, then we can see that the delete
operator had no effect on property d
of obj
.
Object.entries()
The Object.entries()
method returns an array of key-value pairs of an object that are enumerable by the for...in
loop. They are returned in the same order as they are in if they are iterated with the for...in
loop. Each entry of the array will have the key as the first element and the value of the corresponding key as the second element. For example, we can use it to loop through the properties of an object in the following code:
const obj = {
a: 1,
b: 2
};
for (let [key, value] of Object.entries(obj)) {
console.log(key, value);
}
When we run the code above, we get a 1
and b 2
. These are the key-value pairs of this object.
Object.freeze()
The Object.freeze()
method freezes an object. This means that all properties’ values in an object can’t be changed. Also, new properties can’t be added to it, and existing property descriptors for the frozen object can’t be changed. The object is frozen in place. This method doesn’t return a new frozen object. Instead, it returns the original object before it’s frozen. The frozen object’s prototype also can’t be changed. For example, if we run the following to freeze an object:
const obj = {
a: 1
};
Object.freeze(obj);
obj.a = 2;
console.log(obj.a);
We get that obj.a
is still 1. This is because the object’s properties’ values can’t be changed. If we have strict mode enabled, a TypeError
will be raised. It’s important to note that values that are objects can still be modified. For example, if we have the following code:
const obj = {
a: 1,
b: {
c: 2
}
};
Object.freeze(obj);
obj.b.c = 3;
console.log(obj.b.c);
Then obj.b.c
is 3 since Object.freeze
doesn’t freeze properties that are inside of nested objects unless they’re frozen explicitly. So if we have:
const obj = {
a: 1,
b: {
c: 2
}
};
Object.freeze(obj);
Object.freeze(obj.b);
obj.b.c = 3;
console.log(obj.b.c);
Then obj.b.c
is 2 since we frozen obj.b
so that we can’t modify the value of obj.b
.
The Object
constructor has many more methods for constructing objects from an array of arrays with key and value of properties, and also methods to get property descriptors from objects, property names, property symbols, gets the keys of objects and prevent properties from being added or deleted or modify their property descriptors.