The this keyword


The 'this' Keyword in Practice

    'use strict';
    console.log(this); // returns: window | global object

    const calcAge = function (birthyear) {
        console.log(2037 - birthyear);
        console.log(this) // returns: undefined | if strict mode off ==> returns: window
    };
    calcAge(1994);

    const calcAgeArrow = birthyear => {
        console.log(2037 - birthyear);
        console.log(this) // returns: window
    };
    calcAgeArrow(1994);
    // Arrow function use 'Lexical this' | parent scope

    const jonas = {
        year: 1994,
        calcAge: function () {
            console.log(2037 - this.year);
            console.log(this) // returns: jonas object
        }
    }
    jonas.calcAge();

    // This is point to the Object that is calling the Method
    // We might thing we wrote calcAge method inside of jonas object, that's why 'this' is point to jonas ==NO==
    // The reason why 'this' keyword is point to jonas object just because jonas is calling the Method
    
    const matilda = {
        year: 2017,
    };
    // Method Borrowing
    matilda.calcAge = jonas.calcAge; // Copy Method to one object to other
    matilda.calcAge(); // calling function

    // Method Borrowing //
    // copy method from one object to other

    // *** 'This' keyword pointing on ==> who is 'calling' the method


*** 'this' keyword pointing on ==> who is 'calling' the method

*** This is NOT static. It depends on how the function is called, and its value is only assigned when the function is actually called

Regular Functions vs Arrow Functions

    const jonas = {
        firstName: 'Jonas',
        year: 1991,
        calcAge: function() {
            console.log(this); // returns: Jonas object
            console.log(2037 - this.year);
        },
        greet: () => console.log(`Hey ${this.firstName}`), // returns: Hey undefined
        // Arrow function() does not get its own 'this' keyword
    };
    jonas.greet();

    console.log(this) // returns: window object
    console.log(this.firstName) // undefined
    // Reason: On the window object there is no 'firstName' property so, returns: undefined

Again, What if

    var firstName = 'Matilda';
    //if we declare variables with 'var' it create global property on window/global object
    console.log(this) // window object
    window.firstName = 'Matilda';

    const jonas = {
        firstName: 'Jonas',
        year: 1991,
        calcAge: function() {
            console.log(2037 - this.year);
        },
        greet: () => console.log(`Hey ${this.firstName}`), // returns: Hey Matilda
    };
    jonas.greet();

Solution | Use Regular Function

    const jonas = {
        firstName: 'Jonas',
        year: 1991,
        calcAge() {
            console.log(this); // returns: Jonas object
            console.log(2037 - this.year);
        },
        /*
        greet: () => console.log(`Hey ${this.firstName}`), // returns: Hey undefined
        // Arrow function() does not get its own 'this' keyword
        */
        greet: function () {
            console.log(this); // returns: Jonas object
            console.log(`Hey ${this.firstName}`) // returns: Hey Jonas
        },
    };
    jonas.greet();

***BEST PRACTICE - You should never use Arrow Function as a Method.


Method vs Function

Method and a function are the same, with different terms. A method is a procedure or function in object-oriented programming.


A function is a group of reusable code which can be called anywhere in your program. This eliminates the need for writing the same code again and again. It helps programmers in writing modular codes.

Function inside a Function, Using 'this' keyword

    const jonas = {
        firstName: 'Jonas',
        year: 1991,
        calcAge: function () {
            console.log(this); // returns: Jonas object
            console.log(2037 - this.year); // returns: 46

            const isMillenial = function(){
                console.log(this) // returns: undefined
                console.log(this.year >= 1981 && this.year <=1996);
                // returns: TypeError: Cannot read property 'year' of undefined
            };
            isMillenial();
        },
        greet: function () {
            console.log(this); // returns: Jonas object
            console.log(`Hey ${this.firstName}`) // returns: Hey Jonas
        },
    };
    jonas.greet();
    jonas.calcAge(); // function inside a method

Solution 1 | Pre ES6 Solution

    const jonas = {
        firstName: 'Jonas',
        year: 1991,
        calcAge: function () {
            console.log(this); // returns: Jonas object
            console.log(2037 - this.year); // returns: 46

            // Solution 1 | Pre ES6 solution //
            const self = this; // self or that 
            const isMillenial = function () {
                console.log(self); // returns: jonas object
                console.log(self.year >= 1981 && self.year <= 1996);
                // console.log(this.year >= 1981 && this.year <= 1996);
            };
            isMillenial();
        },
        greet: function () {
            console.log(this); // returns: Jonas object
            console.log(`Hey ${this.firstName}`) // returns: Hey Jonas
        },
    };
    jonas.greet();
    jonas.calcAge(); // function inside a method

Solution 2 | Modern solution using Arrow Function

    const jonas = {
        firstName: 'Jonas',
        year: 1991,
        calcAge: function () {
            console.log(this); // returns: Jonas object
            console.log(2037 - this.year); // returns: 46

            // Solution 1 | Pre ES6 solution //
            /*
            const self = this; // self or that 
            const isMillenial = function () {
                console.log(self);
                console.log(self.year >= 1981 && self.year <= 1996);
                // console.log(this.year >= 1981 && this.year <= 1996);
            };
            */
            // Solution 2 | Modern solution using Arrow Function //
            const isMillenial = () => {
                // Arrow function inherit 'this' keyword from its parent scope
                console.log(this);
                console.log(this.year >= 1981 && this.year <= 1996);
            };
            // Arrow Function inherit 'this' keyqord from parent scope

            isMillenial();
        },
        greet: function () {
            console.log(this); // returns: Jonas object
            console.log(`Hey ${this.firstName}`) // returns: Hey Jonas
        },
    };
    jonas.greet();
    jonas.calcAge(); // function inside a method

Arguments Keyword

👉🏻 Arguments keyword exists but its only exists in the Regular function but not in the arrow function.

👉🏻 Arguments keyword is not important in Modern JavaScript anymore because now we have a Modern Way that dealing with multiple parameters.

    const addExpr = function (a, b) {
        console.log(arguments) // returns: arguments array
        return a + b;
    };
    addExpr(2, 5);
    addExpr(2, 5, 8, 12); // we can add more arguments

    const addArrow = (a, b) => {
        console.log(arguments) // returns: ReferenceError: arguments is not defined
        return a + b;
    };
    addArrow(2, 5, 8)