JavaScript Object Methods and this
Learn JavaScript object methods and the this keyword: defining methods, how this is resolved at call time, method borrowing with call/apply/bind, and more.
Introduction to Object Methods in JavaScript
JavaScript objects are collections of properties, and object methods are functions stored as properties of those objects. Methods let an object do things with its own data, not just hold it.
This guide covers how to define and call methods, how the this keyword links a method back to its object, how to read and modify object state from inside methods, and the most common pitfall in the language: losing this in callbacks. It closes with the practical difference between regular functions and arrow functions.
Defining and Calling Methods
A method is just a property whose value is a function. The shorthand syntax greet() { ... } is the modern way to write one; it is equivalent to greet: function() { ... }.
greet is a method of the user object. It uses this.name to access the name property of the object, demonstrating how methods can act on the data within their own object. You call a method with the same dot syntax used for any property, followed by (): user.greet().
The this Keyword in Methods
The this keyword refers to the object before the dot at the moment the method is called. It is decided at call time, not when the function is written — this is what makes this flexible but also error-prone.
Example: Using this in Methods
In the details method, this is used to refer to the person object itself, allowing access to its name and age properties to produce a personalized message. Because details was called as person.details(), this is person.
Modifying Object Properties
Methods are not only for retrieving property values but also for updating them.
Example: Updating Properties
The promote method updates the jobTitle property and outputs a message reflecting the change. This illustrates how methods can dynamically alter an object's internal state.
Using Methods for Computation
Methods are also useful for performing computations based on object properties.
Example: Calculating Values
The area method calculates the area of the rectangle using the properties width and height. This example shows how methods can encapsulate functionality that operates on the data stored within an object.
Borrowing Methods
Because this is resolved at call time, the same function can run against different objects. This is the foundation of method borrowing.
Example: Borrowing a Method
Here, the speak method from the dog object is assigned to the cat object. When called as cat.speak(), this.name refers to Whiskers, demonstrating that this depends on how the method is called, not where it was defined.
When you can't reassign the method but still want to borrow it, use call, apply, or bind to set this explicitly. See Decorators and forwarding, call/apply for the full treatment.
introduce.call(alice) runs introduce with this set to alice, even though introduce is a standalone function and not a property of either object.
Method Chaining
Method chaining allows multiple methods to be called in a single expression by having each method return this — the object itself. The returned object becomes the target of the next call.
Example: Implementing Method Chaining
Each method in calculator modifies value and returns the object, enabling the chained calls. This pattern enhances readability and is the basis of fluent APIs like jQuery and many array helpers.
Traditional Functions vs. Arrow Functions
In JavaScript, the behavior of the this keyword varies significantly between traditional functions and arrow functions. Understanding this difference is the single most important thing for writing bug-free this-dependent code.
Always be cautious of this losing its context in callbacks or when passing a method as an argument. In such cases this may not refer to the originating object — it may be undefined (in strict mode / modules) or the global object.
Traditional Functions
In a traditional function, this is determined by how the function is called. Here is how it varies:
- Global context: When a function is called with no object before the dot,
thisis the global object (windowin browsers,globalin Node) in non-strict code, andundefinedin strict mode or modules.
- Object methods: When a function is called as a method of an object,
thisrefers to that object.
- Event handlers: When a traditional function is used as an event handler,
thisrefers to the element that received the event.
<button id="myButton">Click me</button>
<p id="output">Click the button to see the result.</p>
<script>
document.getElementById("myButton").addEventListener("click", function () {
document.getElementById("output").innerHTML = "This button was clicked: " + this;
});
</script>Arrow Functions
Arrow functions do not have their own this. Instead, they capture this from the surrounding lexical scope at the moment they are defined. This makes them ideal for callbacks inside a method, where you want to keep the method's this.
- Consistent context in callbacks: Useful when
thismust stay the same inside a callback nested in a method.
Here logActions uses an arrow function inside forEach. The arrow function inherits this from logActions, so it correctly references userProfile.name. A traditional function passed to forEach would receive its own this (the global object or undefined), so this.name would fail.
Do not use an arrow function to define a top-level object method when you rely on this. An arrow function has no this of its own, so it inherits from the surrounding scope (often the global scope) rather than the object — this.name would be undefined.
Practical Example
Let's use a realistic example involving an object that manages a user's online profile, demonstrating both function types side by side:
This example clearly shows how arrow functions help maintain the correct context (this), especially in nested callbacks where a traditional function's dynamic this would silently break.
Losing this and How to Fix It
The classic bug: you extract a method into a variable or pass it as a callback, and this is no longer the object.
When counter.show is detached, calling show() has no object before the dot, so this is lost. bind returns a new function whose this is permanently fixed. The same idea applies to setTimeout(obj.method, 1000) (broken) versus setTimeout(() => obj.method(), 1000) (works). For a deeper look, see Function binding.
Conclusion
Object methods give your data behavior, and the this keyword is what connects a method back to its object. The key rule: this is the object before the dot at call time, so it can change depending on how a function is invoked. Regular functions get a dynamic this; arrow functions capture this lexically, which is exactly what you want for callbacks but wrong for top-level methods. When this is lost, reach for bind, call, or apply.
To go further, explore object references and copying behaviour, constructor functions and new, and decorators with call/apply.