prototype, this and new

More About 'prototype', 'this' and 'new'

Every object has an internal [[Prototype]] link. When a lookup misses on the object, the engine follows the link, then the next, until it reaches null. Every ordinary function has a prototype property, and new F(args) creates an object linked to F.prototype, runs F with this bound to it, and returns it unless F returns another object. Classes (Classes) are syntax over this model.

The prototype chain of rex, an object created with new Dog
The prototype chain of rex, an object created with new Dog

this is set by the call, not the definition: obj.m() binds obj; a bare m() gets undefined in strict mode (the global object in sloppy scripts); call(), apply() and bind() set it explicitly; arrow functions inherit the enclosing this, which makes them the fix for callbacks that lose it.

Constructor inheritance and the rules for thisJavaScript
"use strict";
function Animal(name) { this.name = name; }
Animal.prototype.speak = function () { return `${this.name} speaks`; };
function Dog(name) { Animal.call(this, name); }      // run the parent constructor
Object.setPrototypeOf(Dog.prototype, Animal.prototype);
Dog.prototype.bark = function () { return `${this.name} barks`; };
const rex = new Dog("Rex");
const { speak } = rex;                               // detached method
console.log(rex.bark(), rex.speak(), rex instanceof Animal, speak.call({ name: "Tom" }));
try { speak(); } catch (e) { console.log(`${e.name}: this is undefined`); }
Output
Rex barks Rex speaks true Tom speaks
TypeError: this is undefined