`this` in JavaScript
The this keyword lets you reference the function's "execution context."
That's a fancy way of saying that this refers to the object that a function
is a property of when you call the function.
// `this` is an implicit parameter to the function
const fn = function() {
  return this;
};
// One way that `this` is set is by attaching the function
// to an object.
const obj1 = { fn };
const obj2 = { fn };
obj1.fn() === obj1; // true
obj1.fn() === obj2; // false
obj2.fn() === obj1; // false
obj2.fn() === obj2; // true
The important thing to note is that, since functions are plain old variables
in JavaScript, this may change. One common way to mess up the value of
this is to assign a function to an object and call the function without
an associated object. This is informally known as the function losing its context.
const fn = function() {
  return this;
};
const obj = { fn };
// If you call `fn()` without a property access `.`, you're
// implicitly setting the function context to `null`.
const myFn = obj.fn;
myFn() == null; // true in strict mode
TLDR: this is an implicit parameter to a function call. It contains
whatever object the function was a property of when it was called.
With Classes
You will often see this in ES6 class methods. In a class method,
this refers to the instance of the object the method is called on.
class MyClass {
  myFunction() {
    return this;
  }
}
const obj = new MyClass();
obj.myFunction() === obj; // true
Arrow Functions
Arrow functions are special because, unlike other functions, they have
lexical context. That means this in an arrow function is the same
as this outside the arrow function, regardless of how you call the
arrow function.
const arrow = () => this;
arrow() == null; // true
const obj = { arrow };
// Even though `arrow()` is attached to an object, it still
// has the same context as the surrounding block.
obj.arrow() == null; // true
obj.arrow() == this; // true
Using bind(), call(), and apply()
Every JavaScript function has a Function#call() function and a Function#apply() function that lets you set the value of this without explicitly attaching the function to an object. You can
think of call() and apply() as letting you set the implicit parameter this explicitly.
There is also a Function#bind() function that creates a copy of the function with a pre-set context.
const fn = function() {
  return this;
};
const obj = {};
fn.call(obj) === obj; // true
fn.apply(obj) === obj; // true
const copy = fn.bind(obj);
copy() === obj; // true
copy === fn; // false