JavaScript Object Methods — Arrow Functions Break 'this'
- A method is just a function stored as a property on an object — it gives your data the ability to act on itself, not just store values.
- 'this' inside a method refers to the object the method belongs to — it's how a method reads and updates its own object's data without needing anything passed in from outside.
- Never define object methods with arrow functions if you need 'this' — arrow functions don't bind their own 'this', which silently breaks everything in ways that are hard to debug.
- Object methods are functions stored as object properties — they let data act on itself
- Use shorthand syntax: methodName() {} instead of methodName: function() {}
- 'this' inside a method refers to the object that owns the method — but only with regular functions
- Arrow functions don't bind their own 'this' — they break method behavior
- Built-in Object.keys(), Object.values(), Object.entries() inspect any object
- Methods show up in Object.keys() — use typeof filter to exclude them from loops
Quick Debug Cheat Sheet for Object Methods
this is wrong/undefined
console.log(this) inside method to see what 'this' actually isobj.constructor.prototype to verify the method is on the prototype if using classesMethod not running when called
console.log(typeof obj.method) — should be 'function'console.log(Object.keys(obj)) to see if method is presentData property shows method source code
Search for the property name without () in your codebaseUse console.log(obj.method()) to confirm correct outputProduction Incident
Production Debug GuideSymptom → Action guide for the most common method-related failures
object.method(). If the method is extracted (e.g., const fn = obj.method), 'this' will be lost — use bind or call.obj.method() not obj.method. The parentheses trigger the function execution.Object.keys() includes methods when you only wanted data properties→Filter with Object.keys(obj).filter(key => typeof obj[key] !== 'function'). Methods are technically properties — they show up.Every app you've ever used is built on data that does things. A user profile doesn't just store a name — it can update itself, calculate a display label, or check whether the account is verified. A shopping cart doesn't just hold items — it can total the price, apply a discount, or check if it's empty. That 'doing' capability is powered by object methods, and it's one of the most important patterns in JavaScript.
Without object methods, you'd write separate functions scattered all over your code — one to greet a user, another to format their name, another to check their status. That gets messy fast. Methods solve this by packaging the behavior directly alongside the data it operates on. The logic lives where it belongs: inside the object itself.
By the end of this article, you'll know exactly how to write methods inside objects, how to use the 'this' keyword to let a method access its own object's data, how to call methods correctly, and how to use JavaScript's powerful built-in object methods like Object.keys(), Object.values(), and Object.entries(). You'll go from 'I sort of get objects' to 'I can actually build something with this.'
What Is an Object Method? Functions That Belong to an Object
A method is just a function — but instead of floating freely in your code, it's attached to an object as one of its properties. That's it. If you already know what a function is, you already know 90% of what a method is.
Here's the mental model: an object has two kinds of properties. Data properties store values — strings, numbers, booleans. Method properties store functions. When a function is stored inside an object, we call it a method.
Why does this matter? Because that method can then use 'this' to refer to the object it's sitting inside. It can read the object's own data, update it, or compute something from it — all without needing anything passed in from outside. The method and the data are teammates living in the same house.
You write a method exactly like you write a normal property, except instead of assigning a string or number as the value, you assign a function. You can use the traditional 'function' keyword or the modern shorthand syntax — both work, and you'll see both in real codebases.
// A plain object representing a user profile const userProfile = { firstName: 'Sarah', lastName: 'Chen', age: 28, // This is a METHOD — a function stored as a property // 'this' refers to the userProfile object itself getFullName: function () { return this.firstName + ' ' + this.lastName; }, // Modern shorthand syntax — does exactly the same thing // No 'function' keyword needed — cleaner and preferred in modern JS greet() { return 'Hi! My name is ' + this.getFullName() + ' and I am ' + this.age + ' years old.'; }, // A method that UPDATES the object's own data celebrateBirthday() { this.age = this.age + 1; // increment age on the object itself return 'Happy birthday, ' + this.firstName + '! You are now ' + this.age + '.'; } }; // Calling a method: objectName.methodName() console.log(userProfile.getFullName()); // call getFullName method console.log(userProfile.greet()); // call greet method console.log(userProfile.celebrateBirthday()); // call celebrateBirthday — also changes age console.log('Updated age:', userProfile.age); // confirm the age was actually updated
Hi! My name is Sarah Chen and I am 28 years old.
Happy birthday, Sarah! You are now 29.
Updated age: 29
function() {}') is preferred in modern JavaScript. It's less to type, easier to read, and is what you'll see in professional codebases. Use it by default unless you have a specific reason not to.The 'this' Keyword Inside Methods — How a Method Knows Its Own Data
'this' is the word that makes methods genuinely useful. It's a special keyword that, inside a method, points to the object the method belongs to. It's how a method says 'I want to use MY object's data, not some variable from somewhere else.'
Imagine you're an employee at a company. When you say 'my manager', you don't need to explain who you are — 'my' automatically refers to you and your specific context. 'this' works the same way inside a method. When a method says 'this.name', it means 'the name property of the object I belong to.'
This is why methods are more powerful than regular functions for object-related work. A standalone function would need the object passed in as a parameter every single time. A method already knows which object it belongs to, so it can access that data directly.
The key rule to remember for now: inside a method written with 'function' keyword or shorthand syntax inside an object literal, 'this' is the object to the left of the dot when you call the method. 'userProfile.greet()' — 'this' is 'userProfile'. Clear, predictable, useful.
// A bank account object — notice how every method uses 'this' // to access and modify the account's OWN data const bankAccount = { ownerName: 'Marcus Johnson', balance: 1000, currency: 'USD', // 'this.balance' reads the balance from THIS specific object getBalance() { return this.ownerName + "'s balance: " + this.currency + ' ' + this.balance; }, // 'this.balance' is updated — changes the object's own property deposit(amount) { if (amount <= 0) { return 'Deposit amount must be greater than zero.'; } this.balance = this.balance + amount; // update THIS object's balance return 'Deposited ' + amount + '. New balance: ' + this.balance; }, withdraw(amount) { if (amount > this.balance) { // 'this.balance' checks THIS account's funds — not some global variable return 'Insufficient funds. Current balance: ' + this.balance; } this.balance = this.balance - amount; return 'Withdrew ' + amount + '. Remaining balance: ' + this.balance; }, // A method calling OTHER methods on the same object using 'this' printStatement() { return [ '--- Account Statement ---', 'Owner: ' + this.ownerName, this.getBalance() // calling another method via 'this' is valid! ].join('\n'); } }; console.log(bankAccount.getBalance()); console.log(bankAccount.deposit(500)); console.log(bankAccount.withdraw(200)); console.log(bankAccount.withdraw(5000)); // try to overdraw console.log(bankAccount.printStatement());
Deposited 500. New balance: 1500
Wwithdrew 200. Remaining balance: 1300
Insufficient funds. Current balance: 1300
--- Account Statement ---
Owner: Marcus Johnson
Marcus Johnson's balance: USD 1300
Built-In JavaScript Object Methods — Object.keys(), Object.values(), and Object.entries()
JavaScript ships with several powerful built-in methods that sit on the global 'Object' constructor (capital O). These aren't methods you call on your object — you pass your object into them. They're utility tools for inspecting and working with any object.
Think of them like tools in a toolbox. Your object is a box of stuff. Object.keys() gives you a list of all the labels on the box. Object.values() gives you a list of all the actual contents. Object.entries() gives you both — each label paired with its contents — which is perfect for looping.
Object.keys() returns an array of all the property names (keys) of an object. Object.values() returns an array of all the property values. Object.entries() returns an array of [key, value] pairs. All three ignore inherited properties and only return the object's own directly-defined properties.
These three are genuinely used every day in professional JavaScript. Object.entries() combined with a loop or .map() is one of the most common patterns for transforming data, building UI components, and debugging. Learning them now will pay off immediately.
// A product in an online store const laptopProduct = { name: 'ProBook 15', brand: 'TechCore', price: 1299, inStock: true, rating: 4.7 }; // Object.keys() — get all the property NAMES as an array const propertyNames = Object.keys(laptopProduct); console.log('Property names:', propertyNames); // Object.values() — get all the property VALUES as an array const propertyValues = Object.values(laptopProduct); console.log('Property values:', propertyValues); // Object.entries() — get [key, value] pairs — great for looping const propertyPairs = Object.entries(laptopProduct); console.log('Key-value pairs:', propertyPairs); // Real-world use: loop over entries to display each field console.log('\n--- Product Details ---'); Object.entries(laptopProduct).forEach(function ([key, value]) { // Destructure each [key, value] pair directly in the parameter console.log(key + ': ' + value); }); // Object.assign() — copy properties from one object into another // Useful for merging objects or creating shallow copies const discountedProduct = Object.assign({}, laptopProduct, { price: 999, onSale: true }); // {} is the target (new empty object), laptopProduct is copied in, then overrides are applied console.log('\nOriginal price:', laptopProduct.price); // original unchanged console.log('Discounted price:', discountedProduct.price); // new object has new price console.log('On sale flag:', discountedProduct.onSale); // new property added // Object.freeze() — lock an object so nothing can change it const appConfig = Object.freeze({ apiUrl: 'https://api.example.com', version: '2.1.0', maxRetries: 3 }); appConfig.version = '9.9.9'; // silently fails in non-strict mode console.log('\nConfig version (unchanged):', appConfig.version); // still 2.1.0
Property values: [ 'ProBook 15', 'TechCore', 1299, true, 4.7 ]
Key-value pairs: [ [ 'name', 'ProBook 15' ], [ 'brand', 'TechCore' ], [ 'price', 1299 ], [ 'inStock', true ], [ 'rating', 4.7 ] ]
--- Product Details ---
name: ProBook 15
brand: TechCore
price: 1299
inStock: true
rating: 4.7
Original price: 1299
Discounted price: 999
On sale flag: true
Config version (unchanged): 2.1.0
Object.assign() only does shallow copy — nested objects are shared by reference.JSON.stringify()) is a common fallback but drops functions and undefined.Object.keys(), .values(), .entries() are daily tools for inspecting objects.Adding Methods to Existing Objects and Checking What an Object Can Do
You're not locked in to only the methods you define when you first create an object. JavaScript lets you add new methods to an existing object at any time — you just assign a function to a new property name. This is incredibly flexible and comes up constantly when you're building dynamic applications.
You might start with a plain data object from an API — just properties, no methods. Then in your application code, you can bolt on methods to give it behavior. It's like receiving a plain contact card and then writing your own notes and shortcuts on it.
You can also check whether a method (or any property) exists on an object before trying to call it using 'typeof' or the 'in' operator. This prevents runtime errors in situations where you're not sure what shape an object will have — which happens all the time when working with data from external APIs.
And if you ever need to remove a method or property from an object, the 'delete' operator does exactly that. It permanently removes the property from the object.
// Start with a plain data object — no methods, just properties const movieRecord = { title: 'The Lost Horizon', director: 'Elena Vasquez', releaseYear: 2019, ratingOutOf10: 8.4, genre: 'Sci-Fi' }; // Add a method to the existing object AFTER creation // Just assign a function to a new property name moviewRecord.getSummary = function () { return this.title + ' (' + this.releaseYear + ') — directed by ' + this.director; }; // Oops — typo above. Let's do it correctly: movieRecord.getSummary = function () { return this.title + ' (' + this.releaseYear + ') — directed by ' + this.director; }; movieRecord.isHighlyRated = function () { // Returns true if rating is 8.0 or above return this.ratingOutOf10 >= 8.0; }; movieRecord.getAgeOfFilm = function () { const currentYear = new Date().getFullYear(); // get the current year dynamically return currentYear - this.releaseYear + ' years old'; }; console.log(movieRecord.getSummary()); console.log('Highly rated?', movieRecord.isHighlyRated()); console.log('Film age:', movieRecord.getAgeOfFilm()); // Check if a method exists before calling it — safe practice if (typeof movieRecord.getSummary === 'function') { console.log('getSummary method exists — safe to call'); } // The 'in' operator checks for ANY property (including non-functions) console.log('Has director property?', 'director' in movieRecord); // true console.log('Has budget property?', 'budget' in movieRecord); // false // Delete a property (or method) from an object console.log('\nBefore delete — genre:', movieRecord.genre); // Sci-Fi delete movieRecord.genre; console.log('After delete — genre:', movieRecord.genre); // undefined // See all current keys to confirm what's on the object console.log('\nAll current keys:', Object.keys(movieRecord));
Highly rated? true
Film age: 6 years old
getSummary method exists — safe to call
Has director property? true
Has budget property? false
Before delete — genre: Sci-Fi
After delete — genre: undefined
All current keys: [ 'title', 'director', 'releaseYear', 'ratingOutOf10', 'getSummary', 'isHighlyRated', 'getAgeOfFilm' ]
Object.keys() just like data properties do. If you want to loop only over data properties (not functions), filter with: Object.keys(obj).filter(key => typeof obj[key] !== 'function'). This is a common real-world pattern when serializing objects.Object.keys().Method Chaining: Return 'this' to Build Fluent APIs
You've seen it in jQuery, Lodash, and even JavaScript's array methods: chaining calls like arr.filter().map().reduce(). You can build the same pattern in your own objects. The trick: each method returns the object itself ('this'), so the next method can be called directly on the result.
Method chaining reduces noise. Instead of nesting functions or storing intermediate results in multiple variables, you chain calls. The code reads left-to-right, like a sentence: 'object.firstMethod().secondMethod().thirdMethod()'.
To enable chaining, every method that's intended to be chained must 'return this;' at the end. Methods that return a value (like a getter) break the chain — you can't call another method on a string or number. Chaining works best with setter-like methods that modify the object and then hand it back.
// A calculator object with chainable methods const calculator = { value: 0, add(n) { this.value += n; return this; // enable chaining }, subtract(n) { this.value -= n; return this; }, multiply(n) { this.value *= n; return this; }, getResult() { return this.value; // breaks the chain — returns a number } }; // Chained calls — clean and readable const result = calculator .add(10) .subtract(2) .multiply(3) .getResult(); console.log('Result:', result); // (10 - 2) * 3 = 24 // Without chaining — intermediate variables everywhere const calc2 = { value: 0 }; calc2.value += 10; calc2.value -= 2; calc2.value *= 3; console.log('Manual result:', calc2.value); // Real-world: form builder using chaining const formBuilder = { fields: [], addField(type, label) { this.fields.push({ type, label }); return this; }, build() { return this.fields; } }; const myForm = formBuilder .addField('text', 'Name') .addField('email', 'Email') .addField('submit', 'Send') .build(); console.log('Form fields:', myForm);
Manual result: 24
Form fields: [
{ type: 'text', label: 'Name' },
{ type: 'email', label: 'Email' },
{ type: 'submit', label: 'Send' }
]
- Return 'this' from every setter-like method to enable chaining.
- Terminal methods (like
build()or getResult()) return a value and end the chain. - Chaining eliminates intermediate variables — code flows top to bottom.
- Over-chaining can hurt readability if the chain is longer than 5–7 calls.
Object Methods in Practice: Real-World Patterns
You've learned the mechanics. Now let's see where object methods shine in production code. The most common patterns are: factory functions that return objects with methods, methods that coordinate multiple internal calls, and methods that serialize the object for networking.
Factory functions are a clean alternative to classes when you need to create multiple objects with the same behavior. You write a function that returns a new object with methods. Each call creates a fresh object with its own data and the same method definitions. This avoids the confusion of 'this' in classes and is common in React's functional components and in configuration objects.
Another pattern is a method that aggregates data from multiple sources. For example, a 'getSummary' method might concatenate several computed properties instead of requiring the caller to do it. This keeps the formatting logic inside the object, not scattered across the codebase.
Finally, a 'toJSON' method is a JavaScript convention. If an object has a toJSON method, JSON.stringify() will call it automatically. This lets you control exactly how your object is serialized — filter out sensitive fields, rename keys, or flatten structures.
// 1. Factory function — returns a new object with methods function createUser(firstName, lastName, age) { return { firstName, lastName, age, getFullName() { return `${this.firstName} ${this.lastName}`; }, canDrink() { // Age check based on US law — could be configurable return this.age >= 21; } }; } const user1 = createUser('Alice', 'Smith', 30); const user2 = createUser('Bob', 'Jones', 17); console.log(user1.getFullName(), user1.canDrink()); // Alice Smith true console.log(user2.getFullName(), user2.canDrink()); // Bob Jones false // 2. Method that aggregates multiple data sources const order = { items: [ { name: 'Widget', price: 10, qty: 2 }, { name: 'Gadget', price: 25, qty: 1 } ], discount: 5, // flat $ discount getSubtotal() { return this.items.reduce((sum, item) => sum + item.price * item.qty, 0); }, getTotal() { return this.getSubtotal() - this.discount; }, getSummary() { return `Order: $${this.getTotal()} (${this.items.length} items, discount $${this.discount})`; } }; console.log(order.getSummary()); // 3. toJSON method — custom serialization const user = { name: 'John', password: 'secret', role: 'admin', toJSON() { // Serialize only safe fields return { name: this.name, role: this.role }; } }; console.log(JSON.stringify(user)); // {"name":"John","role":"admin"}
Bob Jones false
Order: $65 (2 items, discount $5)
{"name":"John","role":"admin"}
JSON.stringify(). Any object with toJSON will be serialized using that method. Use it to strip sensitive data (passwords, tokens) before sending objects over the network.| Aspect | Object Method (Custom) | Built-In Object Method |
|---|---|---|
| Where it lives | Inside your object as a property | On the global Object constructor |
| How you call it | myObject.methodName() | Object.keys(myObject) |
| Uses 'this'? | Yes — 'this' is the object it belongs to | No — takes the object as an argument |
| Purpose | Give specific objects their own behavior | Utility operations that work on any object |
| Can you modify it? | Yes — reassign or delete at any time | No — these are built-in and read-only |
| Common examples | greet(), calculateTotal(), isActive() | Object.keys(), Object.values(), Object.freeze() |
| When to use | When the logic belongs to that specific object | When you need to inspect, copy or lock objects |
🎯 Key Takeaways
- A method is just a function stored as a property on an object — it gives your data the ability to act on itself, not just store values.
- 'this' inside a method refers to the object the method belongs to — it's how a method reads and updates its own object's data without needing anything passed in from outside.
- Never define object methods with arrow functions if you need 'this' — arrow functions don't bind their own 'this', which silently breaks everything in ways that are hard to debug.
Object.keys(),Object.values(), andObject.entries()are your three daily tools for inspecting objects —entries()is especially powerful because you get both the key and value together, perfect for looping and transforming data.- Return 'this' from methods to enable fluent chaining — it turns sequential calls into a clean pipeline.
⚠ Common Mistakes to Avoid
Interview Questions on This Topic
- QWhat is the difference between a function and a method in JavaScript? Can you show me an example of each?JuniorReveal
- QWhat does 'this' refer to inside an object method, and what happens to 'this' if you use an arrow function instead of a regular function when defining that method?Mid-levelReveal
- QIf I do 'const copy = Object.assign({}, originalObject)', is 'copy' a completely independent clone of the original? What happens if I change a nested property inside 'copy'?Mid-levelReveal
Frequently Asked Questions
What is the difference between a method and a function in JavaScript?
A function is a standalone block of reusable code. A method is also a function, but it's attached to an object as one of its properties. The key difference is context — a method can use 'this' to access the object it belongs to, while a standalone function has no automatic connection to any object's data.
Why does 'this' return undefined inside my object method?
This almost always happens when you define the method using an arrow function (=>). Arrow functions don't create their own 'this' binding — they inherit 'this' from their surrounding scope, which is usually the global scope (or undefined in strict mode). Switch to the shorthand method syntax like 'greet() {}' or 'greet: function() {}' and 'this' will correctly point to your object.
How do I loop through all the methods and properties of a JavaScript object?
Use Object.entries(yourObject) with a forEach loop or a for...of loop. This gives you each [key, value] pair. If you only want data properties (not methods), filter out functions with: Object.entries(yourObject).filter(([key, value]) => typeof value !== 'function'). Object.keys() and a regular for...in loop also work, but for...in includes inherited properties which you usually don't want.
Can I add a method to an object after it's been created?
Yes. Simply assign a function to a new property on the object: myObject.myNewMethod = function() { ... }. The method becomes an own enumerable property and will appear in Object.keys(). You can also delete it later with 'delete myObject.myNewMethod'.
How do I chain methods like jQuery does?
Each method that should be chainable must return the object itself — 'return this;'. Terminal methods that return a value (like a getter) break the chain. For example: const calc = { value: 0, add(n) { this.value += n; return this; }, result() { return this.value; } }; calc.add(5).add(3).result() // 8
Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.