Object Oriented JavaScript In a Easy Way [Part-1]

Object Oriented JavaScript In a Easy Way [Part-1]

What is Object Oriented Programming In JavaScript?

Object Oriented Programming is a popular style of programming which has been holding the roots of JavaScript since the beginning.

If you already have prior experience with Object Oriented Programming in another language, please put aside the knowledge you have, and read through the entire module with a beginner's mind.

This is because Object Oriented Programming in JavaScript is very different from Object Oriented Programming in Other Languages. It is more difficult than it really is.

Now, lets begin by finding out what OOP's in JavaScript is about :

Creating objects from a common object :

Objects in JavaScript have properties and methods. These objects can resemble real-life things.

here, we are trying to construct a user object in JavaScript. A user has a firstName, lastName and an age . We could add these attributes as properties in JavaScript.

User has some details and we can extract these details through function getDetails() , we can write this function as a method in the user object as well.

By using this method, for every new user, we have to write this whole code again which will make the code long and messy.

Instead of using the above method, we can create a function(or something similar) which will make individuals.

Then construct a function that has a this keyword, and we will create individuals with new keyword.

Note: In Object Oriented Programming, the first letter of the constructor is capitalized (User), while each instance is written like a normal variable ( akash, abha etc..).

This small differentiation instantly shows you the difference between constructors and instances in your code.

What's "this"?

this is a keyword in JavaScript. When it is used in a constructor, it refers to the instance that is created with the constructor.

this is a very important concept in Object Oriented Programming. So you need to be familiar with it.

Unfortunately, the value of this in JavaScript changes depending how you call a function, which is unexpected, and can cause a lot of confusion.

So, you'll learn more about this in the given lesson to help you familiarize with the different possible values this can take up.

How To Master JavaScript's "this" Keyword!!

There are 4 layer of oops in js :

  • Layer 1 - Object Orientation with single objects
  • Layer 2 - Prototype Chains of Objects
  • Layer 3 - Constructors as factories for instances, similar to classes in other languages
  • Layer 4 - Sub classing, creating new constructors by inheriting from existing ones

These 4 Layers in Nutshell :

  • Layer 1: Single objects - how do objects, JavaScript's basic OOP building blocks, work in isolation?
  • Layer 2: Prototype Chains: Each Object has a chain of zero or more prototype objects. Prototypes are JavaScript's core inheritance mechanism.
  • Layer 3 : Classes - JavaScript's classes are factories for objects. The relationship between a class and its instance is based on prototypal inheritance.
  • Layer 4 : Sub classing - The relationship between a subclass and its super class is also based on prototypal inheritance.

Layer 1 : Object Orientation with Single Objects

What is Object?

An object in JavaScript is a data type which is composed of a collection of names or keys and values, represented in a key : value pairs. The key : value pairs consist of properties that may contain any data type — including strings, numbers, and Boolean's — as well as methods, which are functions contained within an object.

What are the Properties, Keys & Values?

All objects in JavaScript are maps(dictionaries) from strings to values. an entry in an object is called a Property. The key of property is always a text string and the value of a property can be any JavaScript value, including a function. Methods are properties whose values are functions.

There are three kinds of properties :

  • Properties: These are normal properties in an object, that is mapping from string keys to values. & 1 more is included call as named data properties which include methods
  • Accessors: Special methods whose invocations look like reading or writing properties.(normal properties are storage locations for property values, accessors allow us to compute the values of properties).
  • Internal Properties: These are not directly accessible from JavaScript, but there might be some indirect ways of accessing them :

    Example : [[Prototype]]holds the prototype of an object and is readable via Object.getPrototypeof().

Two Roles of objects in JavaScript :

  • Object as Records
  • Object as Dictionaries

Object as Records :

  • Records : Objects-as-records have a fixed number of properties, whose keys are known at development time. Their values can have different types.

Object as records are created via so-called object-literals. object literals is a stand out feature of JavaScript: which allows us to directly create object without a need for classes.

Example :

Dot Operator (.): Accessing Properties via Fixed Keys :

  • Getting Properties : Dot operator allows us "get" a property (read its value).
  • Calling Methods : Dot operator is also used for call methods.
  • Setting Properties : For setting up values, we use assignment operator (=) via dot notation.
  • Deleting Properties : The delete operator allows us to completely remove a property (The whole key-value pair).

delete returns false , if the property is an own property which cannot be deleted. otherwise returns true in all other cases.

delete returns true even if it doesn't change anything (inherited properties are never removed)

    delete user.toString // true
    console.log(user.toString) // [λ: toString] (Still Exists)

Accessors : There are two kinds of accessors in JavaScript :

  1. Getter (reading) a property.
  2. Setter (writing) a property.
  • Getter : A getter is created by prefixing a method definition with the keyword get :
  • Setter : A setter is created by prefixing a method definition with the keyword set :

Spreading into object Literals (...)

Inside an object literal, a spread property adds the properties of an another object to the current one :

Methods :

We know that the ordinary functions play several roles. Method is one of those roles.

Example :

  • Call : call is a function that allows us to call/invoke/activate another function. When we use call to call a function, we can change the this context.

Example :

call is used to borrow methods from another function (or method).

Example : Let's say you have an array of numbers. You want to use slice to copy the numbers into a new array. One way to use slice is to call the slice method through the numbers array.

Another way through call Is when you use call, you need to pass the numbers array as the this context.

But why we use this Array.prototype.slice.call over array.slice when its so complicated?

People use call with array methods because most array methods (like slice, forEach, filter, and map) work with both arrays and array-like object.

Example : We can also do operations on array-like object.

    const obj = { foo: [1, 2, 3] }
    const arrayMethods = Array.prototype.reverse.call(obj.foo)
    console.log(arrayMethods) // [3, 2, 1]
  • Apply()

The only difference between call and apply method is the way argument is passed. In case of apply method, second argument is an array of arguments where as in case of call method, arguments are passed individually.

Note : With ES6, there's no need for apply Method because we can spread arrays with the spread operator.

  • Bind()

bind allows you to change the this context as well. However, instead of invoking the function immediately, bind returns a function with the parameters you have provided.

Unusual Property keys :

We can't use reserved words (such as var and function) as a variable names, but we can use them as property keys :

    var obj = { var: 'a', function: 'b' };
    obj.var //'a'
    obj.function //'b'

Object as Dictionaries :

Dictionaries: Objects-as-dictionaries have a variable number of properties, whose keys are not known at development time. All of their values have the same type.

Object work best as records. But before ES6, JavaScript did not have a data structure for dictionaries (ES6 brought Maps). Therefore, objects had to be used as dictionaries. As a consequence, keys had to be strings, but values could have arbitrary types.

Arbitrary fixed strings as property keys :

As we move forward from object-as-records to object-as-dictionaries, There will be an important change is that we must be able to use arbitrary strings & numbers as property keys.

Bracket Operator ([ ]): Accessing Properties via Computed Keys

Bracket Operator allow us to refer to a property via an expression.

  • Getting Properties
  • Calling methods
  • Setting Properties
  • Deleting Properties

Detecting Properties :

We will use the in operator to detect the properties because in operator checks if the given key exists in the hash table and it considered as the best way to determine whether the property exists in an object. Also, for performance wise it won't delay.

In some cases, we might want to check for the existence of a property only if it is an own property. in operator checks for both own properties and prototype properties. So we will need to take a different approach hasOwnProperty() function, if returns true when the property owns by the object, and returns false for prototype property.

In given example 'toString' is a prototype property.

Advanced Methods :

Standard Methods :

Object.prototype defines several standard methods which can be overridden. Two important ones are :

  • .toString: configures how objects are converted to strings : Mainly it can be useful for debugging purposes
  • .valueOf: configures how objects are converted to numbers

Enumeration :

By default, all properties that you add to an object are enumerable, which means that you can iterate over them using a for-in loop. Enumerable properties have their internal [[Enumerable]] attributes set to true. The for-in loop enumerates all enumerable properties on an object.

You can easily understand this with the help of given example :

If you want to list all of an object's properties to use later in your program. ECMAScript 5 Introduced the Object.keys () method to retrieve an array of enumerable property names.

Note: Not all the properties are enumerable.

In fact, most of the native methods on objects have their [[Enumerable]] attribute set to false. You can check whether a property is enumerable by using the propertyIsEnumerable() method, which is present on every object:

Property Attributes & Property Descriptors

Property Attributes : Property attributes are the atomic building block of properties.

All of a property's state, both its data and its metadata, is stored in attributes. They are fields that a property has, much like an object has properties.

  • Attributes keys are often written in double brackets.
  • Attributes matter for normal properties and for accessors.

Property Descriptor : It is a data structure for working programmatically with attributes.

Common Attributes :

  • Enumerable : Determines whether you can iterate over the property or not.
  • Configurable : Determines whether the property can be changed or not.

1. Data Property Attributes : ( Contains Extra Two )

  • Value : Which holds the property value ( You can understand it better in example )
  • Writable : Which is a Boolean value indicating whether the property can be written or not.

2. Accessor Property Attributes ( Contains Different Two )

Accessors properties also have two additional attributes. As there is no value stored for accessor properties, that's why it is no need for [[value]] or [[writable]].

  • Get : Contains Getter Function
  • Set : Contains Setter Function

3. Multiple Properties

It's also possible to define multiple properties on an object simultaneously if you use Object.defineProperties() instead of Object.defineProperty()

4. Retrieval Method

If you want to fetch property attributes, you can easily do with using Object.getOwnPropertyDescriptor().

  • Object.getOwnPropertyDescriptor() : Returns an object with enumerable, configurable, writable, value

Preventing Object Modification : To Making objects Immutable

As we know that objects are by default mutable means we can add new properties to it but to prevent these additions we have attribute called [[Extensible]], which is Boolean in nature.

if [[Extensible]] is false then we can prevent new properties from being added to an object.

By default, [[Extensible]] is set to be a true on every object

There are also three different ways to preventing objects from modification :

  1. Preventing Extensions
  2. Sealing Objects
  3. Freezing Objects

1. Preventing Extensions

In this method, we can use Object.preventExtensions() method. After this we'll never be able to add any new properties to it again.

We can also check the value of [[Extensible]] by using method Object.isExtensible()

Example :

2. Sealing objects

In this method, we can use Object.seal() method and this function seal the object which means that we neither only add properties nor can remove or change their types.

Example :

3. Freezing Objects

In this method we can use Object.freeze() method and this function freezes the object. which is similar to sealing function but in this method we can't also write the existing properties.

Data properties in this method are read only.

Note : frozen object can't become unfrozen

Example :