Understanding JavaScript objects
FidelVe
Posted on November 9, 2019
Have you ever read the sentence, "In JavaScript (nearly) everything is an object"?. I'm willing to bet that you have, and probably when you were learning JavaScript, at least in my case I did.
But this is not just for the case of JavaScript, actually, if you google "everything is an object", you will see the same sentence referring to a plethora of programming languages (especially Python).
For someone that is just starting to learn how to code, reading something like that can do more harm than good, you don't even yet understand what an object is and someone is telling you that everything is an object? what are you suppose to do with that information?.
So, let's try again to understand, what is an object in Javascript.
Javascript data types
To understand what objects are, we need to understand what is a data type.
In computer science and computer programming, a data type or simply type is an attribute of data which tells the compiler or interpreter how the programmer intends to use the data.
Basically, a type is an attribute of all the variables (or constants) you are creating when you are coding, in the case of JavaScript, there are 8 data types:
- Undefined
- Null
- Boolean
- String
- Symbol
- Number (Number type and BigInt type)
- and Objects
Out of these data types, 7 are considered primitives (Undefined
, Null
, Boolean
, String
, Symbol
, Number
and BigInt
) and Objects
are what we call references.
What does it mean for Objects
to be references? lets see an example. Let's declare a couple variables like this:
> let foo = 42;
> let bar = foo;
> bar
42
If we modify the variable foo
, the variable bar
will maintain its initial value of 42 (like expected).
> let foo = 42;
> let bar = foo;
> foo = 43;
> bar
42
> foo
43
In the case of Objects
we see a different behaviour:
> let foo = { key: 42 };
> let bar = foo;
> bar
{ key: 42 }
> foo.key = 43;
> bar
{ key: 43 }
As you can see, changing the value of a key in foo
will affect bar
. If you need to make a copy of and Object
and modify the original Object
without this affecting your copy, there's several ways of doing this, I tend to prefer the relatively new spread
operator:
> let foo = { key: 42 };
> let bar = { ...foo };
> bar
{ key: 42 }
> foo.key = 43;
> bar
{ key: 42 }
An in-depth look at Objects
Now that we know what Objects
are, let's talk about what can they contain. Basically, Objects
in JavaScript are a type of data that stores collections of other data in key:value pairs, as simple as that.
In their most simple form they look like this:
let foo = { bar: 1, baz: "two" }
There are some rules about what the keys can be (they can either be a string
or a symbol
), but the values can be basically anything:
let foo = {
one: 1,
two: 'string',
three: { another: 'object' },
four: [ 'an', 'array' ],
five() { return "how about a function? (actually a method)"},
}
This gives us a lot of flexibility when it comes to coding, but can be a little confusing when you are starting to learn about Objects
.
Functions that are inside Objects
are called methods, and with them you can access the data inside the Object
, let's define an Object
the following way:
let rectangle = {
length: 4,
width: 2,
area() {
return this.length * this.width
}
}
Now we can do things like this:
> rectangle.area()
8
> rectangle.width = 4
> rectangle.area()
16
As you can see Objects
can be more complex than you might initially imagine and is that flexibility that allows us to do more interesting things with our code.
Why is (almost) everything in JavaScript an Object?
As we have already seen, Objects
can have very complex shapes, you can have any data type as values inside an Object
(called properties), and you can define functions inside your Objects
(which are called methods) to access those properties.
Now that you know about this shape that Objects
can have, other things are going to start looking very familiar.
Object wrappers for Primitives
Let's take a look at the primitives we already discussed at the beginning.
> let num = 42;
> num.toString()
'42'
Does the expression num.toString()
looks familiar to you?, if it does is because it's a method call, just like we did earlier with the rectangle.area()
example.
But why numbers have methods if they are not objects? (you may ask), well, almost all primitive values (except for null
and undefined
) have an object equivalent or wrapper that wraps around the primitive value to allow us to make things like num.toString()
and make our life easier when coding.
Lets get one thing clear, this does not mean that numbers or other primitives are Objects
, when for example you try to access a property of a string, JavaScript coerces said string to an Object
(the String
wrapper), this all happens under the hood, you do not have to worry about what is going on behind the curtains, but its good that you understand it.
Lets see what methods and properties does the Number
object wrapper has:
> Object.getOwnPropertyNames(Number)
[ 'length',
'name',
'prototype',
'isFinite',
'isInteger',
'isNaN',
'isSafeInteger',
'parseFloat',
'parseInt',
'MAX_VALUE',
'MIN_VALUE',
'NaN',
'NEGATIVE_INFINITY',
'POSITIVE_INFINITY',
'MAX_SAFE_INTEGER',
'MIN_SAFE_INTEGER',
'EPSILON' ]
> Object.getOwnPropertyNames(Number.prototype)
[ 'constructor',
'toExponential',
'toFixed',
'toPrecision',
'toString',
'valueOf',
'toLocaleString'
As you can see there's several very handy properties and methods for the object wrapper Number
and you can access them as you would on any other Object
.
Arrays and Functions
Other things in the list of things that are objects, are the Arrays
and Functions
. So far you might have learned that Arrays
are ordered list, and this is truth but, under the hood, Arrays
are Objects
too.
> let someArray = ['foo', 'bar', 'baz']
> someArray
[ 'foo', 'bar', 'baz' ]
> Object.getOwnPropertyNames(someArray)
[ '0', '1', '2', 'length' ]
> Object.getOwnPropertyNames(Array.prototype)
[ 'length',
'constructor',
'concat',
'find',
'findIndex',
'pop',
'push',
'shift',
'unshift',
'slice',
'splice',
'includes',
'indexOf',
'keys',
'entries',
'forEach',
'filter',
'map',
'every',
'some',
'reduce',
'reduceRight',
'toString',
'toLocaleString',
'join',
'reverse',
'sort',
'lastIndexOf',
'copyWithin',
'fill',
'values' ]
For the case of Functions
we have the following:
> function foo(param1, param2) {return [param1, param2]}
> Object.getOwnPropertyNames(foo)
[ 'length', 'name', 'arguments', 'caller', 'prototype' ]
> foo.length
2
As you can see we have for example a property called length
, this value indicates how many parameters the function expect.
And if we call Object.getOwnPropertyNames()
on the Function.prototype
we have other interesting stuffs:
> Object.getOwnPropertyNames(Function.prototype)
[ 'length',
'name',
'arguments',
'caller',
'constructor',
'apply',
'bind',
'call',
'toString' ]
>
Let's wrap things up
There's a lot of details in terms of what are prototypes
, constructors
and what is an instance
that I'm purposely not talking about or getting into too much detail, I wanted for this article to be just an overview of Objects
in JavaScript for people that are still learning the basics.
The important thing to know is that Objects
are everywhere in JavaScript, and is important to understand them in order to improve your JavaScript skills.
If you are new to programming and have any questions about objects in JavaScript, put it in the comments!
Thanks for reading!.
Posted on November 9, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.