# Creating objects with functions, one level deeper.

Basic functionality of function is like a computer. We input some properties, a function does what is defined inside it and gives an output.

In JavaScript a majority of functions are used to create objects.
It is because an object can store both *Data types* and *Structural types*.

Data types are also called primitives, they include *undefined*, *boolean*, *number*, *string*, etc.
Structural types, also known as non-data types include *objects*, *arrays*, *functions*, etc.

You can find more about Data types and Structural types [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures).

Lets look at some ways of creating objects using different types of functions.

### Factory Function
It is the simplest way of returning the objects.

For example, 
Let us say, we need an object which stores firstName, lastName of a person and also a method to log the fullName of the person in the console.

It goes like this...

```
function FacPerson(firstName, lastName){
  return {
    firstName,
    lastName, 
    fullName() {
      console.log(this.firstName + " " + this.lastName);
    }
  }
}

const aPerson = FacPerson("John", "Wick");
aPerson.fullName();
```
Note that I used *this* object to call the input i.e., firstName and lastName. We will discuss it shortly.

What is happening in the code?
Person function returns an object with firstName, lastName and the method fullName.
aPerson is assigned the object generated by Person function which has the values "John" as firstName and "Wick" as lastName.
In the last line the fullName method is called. This should log "John Wick" in the console.

### Constructor Function
In a constructor function the object is not explicitly returned like in the case of factory function. Instead a *this* object is implicitly returned when a *new* instance is created.

It goes like this...

```
function ConPerson(firstName, lastName){
  this.firstName = firstName;
  this.lastName = lastName;
  this.fullName = function(){
    console.log(this.firstName + " " + this.lastName);
  };
}

const anoPerson = new ConPerson("John", "Wick");
anoPerson.fullName();
```
Notice we didn't return anything in the above function? It is because *this* object is implicitly returned.

We will talk about *this* a little later. Let's talk about *new*. 
*new* creates something called an instance. The instance in this case is an object. 
So when a *new* instance is created, the constructor function returns the *this* object. 

Let us see what is happening in the code.
When a *new* instance of Person function is created with values "John" as firstName and "Wick" as lastName, the *this* object is returned.
This returned *this* object is assigned to aPerson.
In the last line the fullName method is called. This should log "John Wick" in the console.

### *this*
Now that we have a preliminary understanding of *this* lets dive deeper.

The *this* have a deeper meaning than we discussed above.
There are many ways of defining a function,
1. Function Declaration
2. Function Expression
3. Arrow Function

Functions inside an object are called methods. In any object values are stored as key-value pairs. Hence a Function Declaration can't be used for defining object methods.

Let us take a look at how *this* behaves inside other two types of function.

Let us create an object with methods defined using Function Expression and Arrow Function and log *this* in the console.

```
function FactoryFunction() {
    return {
        functionExpression: function() {
            console.log(this);
        },
        arrowFunction: () => {
            console.log(this);
        }
    }
}

const facFun = FactoryFunction();
facFun.functionExpression();
facFun.arrowFunction();
```
The above code logs the object returned by FactoryFunction in the case of functionExpression whereas in the case of arrowFunction it logs the *window* object 

*window* object is the object in which details of the entire code is stored.

This is because of how a function expression and arrow function is compiled. A function expression is compiled in its global scope i.e., in the scope of the object inside which it is defined. Where as an arrow function is compiled in lexical scope i.e., in the scope *window* object.

Now lets see how Constructor Function hold

```
function ConstructorFunction() {
    this.functionExpression = function () {
        console.log(this);
    }

    this.arrowFunction = () => {
        console.log(this);
    }   
}

const conFun = new ConstructorFunction();
conFun.functionExpression();
conFun.arrowFunction();
```

The above code logs the object returned by FactoryFunction in both the cases.

This is because of how instances work. When an instance is called, it forms its own *this* object scope and complies the code. Since it inside it's own object the global and lexical scope are the same and hence gives the same result for both function expression and arrow function.

Use the replit below to test it out:

%[https://replit.com/@ikkurthis1998/Creating-objects-with-functions-JavaScript-a-level-deeper#index.js]

### Conclusion
Arrow Functions have shorter syntax than Function Expression. So when writing a function to return an object with methods which needs to access variables which are in it, It is preferable to write a Constructor Function with Arrow Function methods. Or we need to be careful which type of function is being used for defining methods in the case of Factory Function.

