Lesson 2 · 2 of 20
this, bind, call and apply · JavaScript
Understand what this points to in JavaScript and how to pin it down with bind, call and apply, using a shopping cart as the example.

Inside a method, `this` is the object before the dot in the call. That is why cart.describe() can read this.owner and call this.total(): in that call, this is cart. The value of this does not depend on where the function was written but on how it is called.
If you copy the method into a variable (const loose = cart.describe) and call it on its own, there is no object before the dot any more: this is no longer the cart and this.total does not exist, hence the error this.total is not a function. This is the classic bug when you pass a method as a callback, for example to setTimeout or a button click.
`bind` fixes it: cart.describe.bind(cart) returns a new function whose this is locked for good. `call` and `apply`, on the other hand, run the function right away with whatever this you choose: describe.call(otherCart) describes Luis's cart with the same code. They differ only in how they take arguments: call takes them one by one, apply takes an array.
Arrow functions have no this of their own: they use the one from the surrounding function. In labels(), the arrow inside map sees the same this as the method, so every label carries Ana. In DMarlon Studio, JavaScript is the language of the Electron, React, Next.js and React Native targets, and this detail explains why event handlers use so many arrows.
Code · main.js
const cart = { owner: "Ana", items: [12.5, 30, 7.25], total() { return this.items.reduce((sum, price) => sum + price, 0); }, describe() { return `${this.owner} owes ${this.total().toFixed(2)} EUR`; }, // An arrow function has no "this" of its own: it uses the method's one. labels() { return this.items.map((price) => `${this.owner}:${price}`); },};console.log(cart.describe());console.log(cart.labels().join(" "));// Losing "this": the method is called without its object.const loose = cart.describe;try { loose(); } catch (err) { console.log("Lost this:", err.message); }// bind returns a new function with "this" fixed for good.const bound = cart.describe.bind(cart);console.log("bind:", bound());// call and apply run the function now with the "this" you choose.const otherCart = { owner: "Luis", items: [5, 5], total: cart.total };console.log("call:", cart.describe.call(otherCart));function withTax(rate, label) { return `${label}: ${(this.total() * (1 + rate)).toFixed(2)} EUR`;}console.log(withTax.call(cart, 0.21, "Ana with VAT"));console.log(withTax.apply(otherCart, [0.1, "Luis with 10%"]));Output · node main.js
Ana owes 49.75 EUR Ana:12.5 Ana:30 Ana:7.25 Lost this: this.total is not a function bind: Ana owes 49.75 EUR call: Luis owes 10.00 EUR Ana with VAT: 60.20 EUR Luis with 10%: 11.00 EUR
Key points
thisis decided by how a function is called, not where it is written.- A method detached from its object loses its
this. bindreturns a function with a fixedthis;callandapplyrun it immediately.calltakes separate arguments;applytakes an array.- Arrow functions take
thisfrom the surrounding function.
Exercise
Create a cart for Marta with owner and items but no methods, and work out her total with cart.total.call(...). Then replace the arrow in labels() with a regular function and see what happens to this.owner.