Nearly everything in JavaScript is an object other than six things that are not objects which are — null
,undefined
, strings, numbers, boolean, and symbols. These are called primitive values or primitive types. 🤔
Anything that is not a primitive value is an Object. That includes arrays, functions, constructors, and objects themselves.
Yes! Functions and arrays are objects too.😃
Note: We have a whole series of javascript article that cover many core concept that will surly level up your understanding.
Objects 👇
Conceptually, Objects are same in all programming languages i.e they represent real-world things that we want to represent inside our programs with characteristics/properties and methods.
For Eg. If your object is a student, it will have properties like name, age, address, id, etc and methods like updateAddress
, updateNam
, etc.
In javascript, think of an object as a list that contains items, and each item (a property or a method) in the list is stored by a key-value pair in memory as reference.
Let’s see an example:-
const firstObj = {
1: "deepak",
"age": 28
}
firstObj
is an object with 2 properties 1 and age and value as deepak
and 28
.
JavaScript objects are somewhat different in the way they are created. There is no requirement for a class as such.
Object Creation👇
We can create objects in many ways in javascript, let’s look at each one of them.
Object literal
(Direct way) — Object literals are a comma-separated list of key-value pairs wrapped in curly braces. Object literal property values can be of any data type, including array literals, functions, nested object literals or primitive data type.
var student = {
id: 1,
name: "deepak",
age: "27",
updateAddress: () => {
// logic to update address
},
grade: ['A', 'A+', 'A']
}
Note: The student object keys in the above can be accessed via Dot notation i.e student.id, student.name or via a square bracket notation i.e student[‘id’], student[‘name’], etc
2. Object.create()
— the method creates a new object with the specified prototype and properties of the old object.
Note: Every JavaScript function has a prototype
property which .is empty by default. We may attached methods or properties to prototype
.
// syntax - Object.create(prototype[, propertiesObject])
var newStudent = Object.create(student);
// this create a new object with old object added in its prototype // chain
Below is the output of the object and prototype key (__proto__).
Objects in Javascript
We can now add new properties and data to newStudent
object using the method we are learning here.
Note: The newStudent
will have access to the parent student
object keys and value as it’s been added to newStudent
prototype chain and this is one way we do inheritance in javascript. That is, newStudent
will store a link to student
object. This parent object is also looked when a property is read.
The parent can have a parent and so on. This is repeated until we reach an object that does not have any parent i.e the parent is null
.
3. Object Instance
— The use of Object
constructor in conjunction with the “new” keyword allows us to initialize new objects.
Let’s take a look by an example
const newObj = new Object();
newObj.name = 'Deepak';
newObj.location = 'Delhi, India';
However, the above method using new Object()
is not well suited to programs that require the creation of multiple objects of the same kind, as it would involve repeatedly writing the above lines of code for each such object.
To deal with this problem, we can use the next method
4. Object Constructor
— Constructors can be useful when we need a way to create an object “type” that can be used multiple times without having to redefine the object every time and this could be achieved using the Object Constructor function.
Let’s take a look by an example
function Vehicle(name, model) {
this.name = name;
this.model = model;
}
let car1 = new Vehicle('Fiesta', '2019');
let car2 = new Vehicle('DC avanti', '2018');
We created two objects with the same property but with different values.
5. Object.assign()
—this is another method to create a new object from other objects.
Note: We will cover enumerable/ownership in the next part, so bear this with me.
It copies the values of all enumerable own properties from one or more source objects to a target object. It will return the target object. Let’s understand by an examples:-
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
There are a lot of use cases for Object.assign()
like Object cloning, Merging objects, etc.
6. Object.fromEntries()
— method transforms a list of key-value pairs into an object. Let’s take a look by an example
const entries = new Map([
['foo', 'bar'],
['baz', 42]
]);
const obj = Object.fromEntries(entries);
console.log(obj);
// expected output: Object { foo: "bar", baz: 42 }
Note: The best way to create objects is via Literal notation as it takes less space in the source code. It’s clearly recognizable as to what is happening, so using new Object()
, you are really just typing more and (in theory, if not optimized out by the JavaScript engine) doing an unnecessary function call. Also, literal notation creates the object and assigns the property in same line of code which is not the case with others.
Q – How to add/update and remove property of an object?👇
Properties to an object can be added via dot or bracket notation as discussed earlier. Let’s look by an example
const a = {};
a.name = 'deepak';
a['city'] = 'delhi';
a[1] = 'dope';
Here, name
and city
are object properties.
An object can only contain a single key with one value. We can’t have a single key having two different values.
Property names can be a string or a number or special character, or dynamic properties, but if the property name is not a string, it has to be accessed with the bracket notation. So if we need to access property 1
in the above example, we can do a[1]
but a.1
will return a syntax error. However, property case i.e a.name
or a["name"]
will work.
a.first name = 'deepak' // will return syntax error as first name has a space
a['first name'] = 'deepak' // will work
To update a property we can again use both notation types. If we add value to already created properties then the value is updated else created.
a.city = 'new york';
This will update the city value from delhi
to new york
.
We can also create and update properties to an object via Object
function methods like Object.defineProperties()
or Object.defineProperty()
Object.defineProperties(a, {
pincode: {
value: 10012,
writable: true
},
property2: {}
});
console.log(a.pincode); // 10012
To delete a property of an object we can use delete
keyword with both notations (dot and bracket).
delete a['city'];
delete a.city;
The return value of delete
is true
if the property was successfully deleted. Else, it will be false
.
Do you know a way to not to allow properties update or delete? 🤔
If yes, comment down below. If not then, don’t worry I will deep dive into next article with such more questions.
Q – How to iterate on object properties?👇
In practical coding there will be many instances where we want to access all key-value pairs of an object.
Using Loops — for in and for of loops
In case of for in, it iterates over an object and returns the properties one by one.
for (const key in a) {
console.log(key, a[key]);
}
key
will have all the properties one by one and a[key]
will return the value. For in loop also iterate over the prototype chain and will return the parent keys as well, so don’t be surprised if you see more keys. To avoid seeing more keys we can do ahasOwnProperty
check to get the current object keys only.
In case of for of, it iterates over iterating over iterable objects. For more read here.
There are various methods in the Object function which helps to access object properties and values, not the prototype chain.
- Object.keys() or Object.getOwnPropertyNames ()— returns an array of string keys.
const keys = Object.keys(a)
// return ["name", "first name", "city", "1"];
const newKeys = Object.getOwnPropertyNames(a);
// return ["name", "first name", "city", "1"];
keys.map(key => console.log(a[key]));
// return ["deepak", "deepak", "new york", "dope"];
2. Object.values() — returns an array of values.
const keys = Object.values(a);
// return ["deepak", "deepak", "new york", "dope"]
3. Object.entries() — returns an array of [key, value]
pairs.
const data = Object.entries(a);
// returns [ ["1", "dope"], ["name", "deepak"], ["first name", "deepak"], ["city", "new york"]]
From what we see above, the order of appearance of properties is not fixed in an object.
Q – How to check properties existence in an object?👇
There are three ways to check the property existence in an object.
- Using hasOwnProperty — method returns a boolean indicating whether the object has the specified property as its own property, not the parent/inheriting property.
console.log(a.hasOwnProperty(1)); // return true;
console.log(a.hasOwnProperty('1')); // return false;
const b = Object.create(a); // this will add a as parent of b
console.log(b.hasOwnProperty(1)); // return false
Note: hasOwnProperty
returns true even if the value of the property is null
or undefined
.
What if we have hasOwnProperty
as a property name in an object? 🤔 Comment your thoughts below.
2. Using in operator — The in
operator returns true
if the specified property is in the specified object or its prototype chain i.e inside the parent object.
console.log(1 in a); // return true;
console.log('1' in a); // return false;
const b = Object.create(a); // this will add a as parent of b
console.log(b.hasOwnProperty(1)); // return true
Note: hasOwnProperty
only checks for current object property whereas in
operator checks for current+parent properties.
3. Using a custom made function – There are various ways to check if a property exists or not via custom method too. One of them is through Object.keys
For eg.
Object.keys(a).indexOf(1) !== -1 // return true
Comment down below your custom method to do the same 😃.
Q – What are copy by reference/sharing and copy by value and how does it applies to object?👇
The difference is, by the value, we mean that new memory allocation is done each time something is created whereas in case of reference we point to already created memory space/address.
In the context of javascript, all primitive data types are allocated memory via value method and for an object, both copy by value and reference can be used depending upon the implementation.
// pass by value
let a = 5;
let b = a;
a = 6;
console.log(b) // return 5 as each time a new memory is allocated
// pass by reference
const a = {x: 1};
const b = a;
a.x = 3;
console.log(b.x) // it returns 3 as its a shared memory between a and b
Q – What is a shallow and deep copy/cloning of objects?👇
The core difference between shallow and a deep copy is how the properties are copied to the new object.
Shallow and Deep copy
In Shallow copy, the new object share the data with the older object. let’s look by example
We are using =
create a shallow copy b
of a
object.
const a = {x: 1};
const b = a;
a.x = 3;
console.log(b.x) // return 3
A shallow copy will duplicate the top-level properties, but the nested object is shared between the original(source) and the copy(target). In most cases, copy by reference is a shallow copy.
Another way to shallow copy is by the usage of Object.assign()
.
Let’s look at the example
let obj = {
a: 1,
b: {
c: 2,
},
}
let newObj = Object.assign({}, obj);
console.log(newObj); // { a: 1, b: { c: 2} }
obj.a = 10;
console.log(obj); // { a: 10, b: { c: 2} }
console.log(newObj); // { a: 1, b: { c: 2} }
newObj.b.c = 30;
console.log(obj); // { a: 10, b: { c: 30} } <---- obj.b.c = 30
console.log(newObj); // { a: 20, b: { c: 30} }
As we can see above obj.b.c = 30
is a pitfall of Object.assign()
. Object.assign
only makes shallow copies. Both newObj.b
and obj.b
share the same reference to the object because of individual copies were not made, instead, a reference to the object was copied.
In Deep copy, the new object will have its own set of key-value pairs (having the same value as original ones) rather than sharing.
Let’s see some ways to do a deep copy
- JSON.parse(JSON.stringify(object))
let obj = {
a: 1,
b: {
c: 2,
},
}
let newObj = JSON.parse(JSON.stringify(obj));
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } } (New Object!)
The issue with the above is we cannot copy the user-defined object functions or keys whose values are undefined
, or a Symbol
.
let obj = {
a: 1,
b: {
c: 2,
},
d: () => {}
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj); // { a: 1, b: { c: 2 } } (New Object!)
Also, this method doesn’t work for circular objects. Circular objects are objects that have properties referencing themselves. Let’s look by an example.
let obj = {
a: 'a',
b: {
c: 'c',
d: 'd',
},
}
obj.c = obj.b;
obj.e = obj.a;
obj.b.c = obj.c;
obj.b.d = obj.b;
obj.b.e = obj.b.c;
let newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj); // return error.
The above will throw an error saying converting circular structure to JSON.
2. Using the ES6 spread operator —
let obj = {
one: 1,
two: 2,
nested: {
three: 3
},
}
let newObj = { ...obj };
console.log(newObj); // { one:1, two:2, nested: {three: 3}}
(New Object!)
However, nested
is still copied shallowly.
Q – How to compare two objects?👇
The equality ==
and strict equality ===
operators for objects work exactly the same i.e two objects are equal only if they share the same reference to the memory.
Note: For “a == b” to evaluate to true a and b need to be the same value. In the case of “a === b” a and b must be the same value and also the same type for it to evaluate to true.
For instance, if two variables reference the same object, they are equal:
const a = {};
const b = a;
console.log(b == a); // return true
const c = {};
console.log(c == a); //return false
There are lot of other things related to objects that which will we cover in part 2 of this short series.
Comment down below if you have doubts.