The “this” keyword in Javascript behaves a bit differently when we compare it to other languages. What “this” refers to depends on how the function is called.

Global context

this is the current module.exports object (nodejs) and global window object (browser).

/*
    file: globalWebBrowser.js
    usage: Put this code onto console tab of your web browser in development mode
*/

this
//window (global object)

name = 'test'
this.name
//'test'

Object method

this is the object itself.

/*
    file: objectMethod.js
    usage: node objectMethod.js
*/

const obj = {
    firstName: 'Taylor',
    lastName: 'Swift',
    fullName: function() {
        return this.firstName + ' ' + this.lastName
    }
}

console.log(obj.fullName())
//Taylor Swift

Function

this is the object that called the function.

/*
    file: function.js
    usage: node function.js
*/

function myFunction() {
    return this
}

console.log(myFunction())
//Object [global]

console.log(myFunction() === globalThis)
//true

Function (strict mode)

this is undefined.

/*
    file: functionStrictMode.js
    usage: node functionStrictMode.js
*/

function myFunction() {
    'use strict'
    return this
}

console.log(myFunction())
//undefined

console.log(myFunction() === globalThis)
//false

Arrow function

The arrow function does not bind its own this but inherits it from the enclosing lexical context (parent scope).

/*
    file: arrowFunction.js
    usage: node arrowFunction.js
    note: minimum node version required: 6
*/

global.name = "Global Object"

function Test(){
    const myArrowFunction = () => {
        return this
    }
    
    const myTraditionalFunction = function() {
        return this
    }
    
    const myObject = {
        name: "myObject",
        getThis: myArrowFunction,
        getThis2: myTraditionalFunction
    }
    
    console.log('arrow func:', myObject.getThis())
    //Global Object
    console.log('traditional func:', myObject.getThis2())
    //myObject
}

Test()

Class

Within the class constructor, this is a regular object. Then all class non-static methods are added to the prototype of the this object. Meanwhile, in static methods, this refers to class itself.

/*
    file: class.js
    usage: node class.js
*/
class myClass {
    constructor(name) {
        this.name = name
    }

    getName() {
        console.log(this.name)
    }

    static myStaticFunction() {
        console.log(this.name)
    }
}

const _myClass = new myClass('Pineapple')

_myClass.getName()
//Pineapple

myClass.myStaticFunction()
//myClass

Other methods: call(), apply(), bind()

this is the first argument of call(), apply(),bind() regardless of how the function is called.

/*
    file: callApplyBind.js
    usage: node callApplyBind.js
*/

const Paul = {
    firstName: 'Paul',
    lastName: 'Smith',
    logFullname: function(){
        console.log(this.firstName + ' ' + this.lastName)
    },
    introduceSelf: function(yob){
        console.log(`Hello. My name is ${this.firstName} ${this.lastName}. I am ${new Date().getFullYear() - yob} years old`)
    }
}

const Taylor = {
    firstName: 'Taylor',
    lastName: 'William'
}

Paul.introduceSelf(1980)
//Hello. My name is Paul Smith. I am 42 years old

const TaylorIntroducesHerself = Paul.introduceSelf.bind(Taylor, 1990)
TaylorIntroducesHerself()
//Hello. My name is Taylor William. I am 32 years old

Paul.introduceSelf.call(Taylor, 1990)
//Hello. My name is Taylor William. I am 32 years old

Paul.introduceSelf.apply(Taylor, [1990])
//Hello. My name is Taylor William. I am 32 years old

Browser event

this is the element received that event.