JavaScript Object Methods: A Complete Tutorial

Master JavaScript object methods from basic definitions to advanced patterns. Learn how to define methods, use shorthand syntax, understand this binding, chain methods, and work with built-in Object methods with practical examples.

JavaScriptbeginner
15 min read

A method is a function stored as a property of an object. Methods give objects behavior: a user object can have a greet() method, a calculator can have add() and subtract(), and a shoppingCart can have addItem() and getTotal(). Understanding how methods work, how this binds inside them, and how to use built-in Object utility methods are essential skills for every JavaScript developer.

This tutorial covers defining methods, shorthand syntax, this binding rules, method chaining, and the most important built-in Object methods you will use daily.

Defining Object Methods

Function Expression (Classic Syntax)

The traditional way to add a method is assigning a function expression to a property:

javascriptjavascript
const user = {
  name: "Alice",
  age: 28,
  greet: function() {
    return `Hi, I'm ${this.name}`;
  },
  getAge: function() {
    return `I'm ${this.age} years old`;
  }
};
 
console.log(user.greet());  // "Hi, I'm Alice"
console.log(user.getAge()); // "I'm 28 years old"

Method Shorthand (ES6)

ES6 introduced a shorter syntax that removes the : function part. This is the preferred modern style:

javascriptjavascript
const user = {
  name: "Alice",
  age: 28,
  greet() {
    return `Hi, I'm ${this.name}`;
  },
  getAge() {
    return `I'm ${this.age} years old`;
  }
};
 
console.log(user.greet());  // "Hi, I'm Alice"
console.log(user.getAge()); // "I'm 28 years old"

Method Shorthand vs Function Expression

FeatureShorthand greet() {}Expression greet: function() {}
Syntax lengthShorterLonger
this bindingSame (dynamic)Same (dynamic)
Can be a constructorNoYes
super keyword accessYesNo
Preferred in modern JSYesLegacy

Adding Methods After Creation

You can add methods to an existing object at any time:

javascriptjavascript
const calculator = {
  value: 0
};
 
calculator.add = function(n) {
  this.value += n;
  return this;
};
 
calculator.subtract = function(n) {
  this.value -= n;
  return this;
};
 
calculator.reset = function() {
  this.value = 0;
  return this;
};
 
calculator.add(10).subtract(3).add(5);
console.log(calculator.value); // 12

Understanding this in Methods

The this keyword inside a method refers to the object that called the method. It is not determined by where the method is defined, but by how it is called:

javascriptjavascript
const user = {
  name: "Alice",
  greet() {
    return `Hi, I'm ${this.name}`;
  }
};
 
console.log(user.greet()); // "Hi, I'm Alice"
 
// `this` depends on the CALLER
const greetFn = user.greet;
console.log(greetFn()); // "Hi, I'm undefined" (or error in strict mode)

Why Arrow Functions Break this

Arrow functions do not have their own this. They inherit this from the enclosing scope, which makes them unsuitable as object methods:

javascriptjavascript
const user = {
  name: "Alice",
 
  // WRONG: arrow function inherits outer `this` (window/undefined)
  greetArrow: () => {
    return `Hi, I'm ${this.name}`; // `this` is NOT user
  },
 
  // CORRECT: regular method has dynamic `this`
  greetMethod() {
    return `Hi, I'm ${this.name}`; // `this` is user
  }
};
 
console.log(user.greetArrow());  // "Hi, I'm undefined"
console.log(user.greetMethod()); // "Hi, I'm Alice"

Arrow Functions Inside Methods (Valid Use)

Arrow functions are useful inside methods when you need to preserve the method's this in nested callbacks:

javascriptjavascript
const team = {
  name: "Engineering",
  members: ["Alice", "Bob", "Charlie"],
 
  listMembers() {
    // Arrow function inherits `this` from listMembers
    return this.members.map(member => {
      return `${member} - ${this.name} team`;
    });
  }
};
 
console.log(team.listMembers());
// ["Alice - Engineering team", "Bob - Engineering team", "Charlie - Engineering team"]

Method Chaining

Method chaining lets you call multiple methods in sequence by returning this from each method:

javascriptjavascript
class TaskManager {
  constructor() {
    this.tasks = [];
    this.filter = "all";
  }
 
  addTask(title, priority = "medium") {
    this.tasks.push({ title, priority, done: false });
    return this; // Enable chaining
  }
 
  completeTask(title) {
    const task = this.tasks.find(t => t.title === title);
    if (task) task.done = true;
    return this;
  }
 
  setFilter(filter) {
    this.filter = filter;
    return this;
  }
 
  getFilteredTasks() {
    if (this.filter === "done") return this.tasks.filter(t => t.done);
    if (this.filter === "pending") return this.tasks.filter(t => !t.done);
    return this.tasks;
  }
 
  summary() {
    const total = this.tasks.length;
    const done = this.tasks.filter(t => t.done).length;
    return `${done}/${total} tasks completed`;
  }
}
 
const manager = new TaskManager()
  .addTask("Design UI", "high")
  .addTask("Write tests", "medium")
  .addTask("Deploy app", "high")
  .completeTask("Design UI")
  .setFilter("pending");
 
console.log(manager.getFilteredTasks());
// [{ title: "Write tests", ... }, { title: "Deploy app", ... }]
console.log(manager.summary()); // "1/3 tasks completed"

Built-in Object Methods

JavaScript's built-in Object class provides utility methods for inspecting and transforming objects.

Object.keys()

Returns an array of an object's own enumerable property names:

javascriptjavascript
const user = {
  name: "Alice",
  age: 28,
  email: "alice@example.com"
};
 
console.log(Object.keys(user));
// ["name", "age", "email"]

Object.values()

Returns an array of an object's own enumerable property values:

javascriptjavascript
const scores = {
  math: 92,
  science: 88,
  english: 95
};
 
console.log(Object.values(scores));
// [92, 88, 95]
 
// Useful for calculations
const average = Object.values(scores).reduce((sum, s) => sum + s, 0) / Object.keys(scores).length;
console.log(average); // 91.67

Object.entries()

Returns an array of [key, value] pairs, perfect for iteration:

javascriptjavascript
const product = {
  name: "Laptop",
  price: 999,
  brand: "TechBrand"
};
 
for (const [key, value] of Object.entries(product)) {
  console.log(`${key}: ${value}`);
}
// name: Laptop
// price: 999
// brand: TechBrand
 
// Transform to Map
const productMap = new Map(Object.entries(product));
console.log(productMap.get("price")); // 999

Object.fromEntries()

The reverse of Object.entries(). Converts an array of [key, value] pairs back into an object:

javascriptjavascript
const entries = [
  ["name", "Alice"],
  ["age", 28],
  ["role", "developer"]
];
 
const user = Object.fromEntries(entries);
console.log(user); // { name: "Alice", age: 28, role: "developer" }
 
// Useful with Map
const priceMap = new Map([
  ["apple", 1.50],
  ["banana", 0.75],
  ["orange", 2.00]
]);
 
const priceObj = Object.fromEntries(priceMap);
console.log(priceObj); // { apple: 1.5, banana: 0.75, orange: 2 }

Object.assign()

Copies properties from source objects into a target object:

javascriptjavascript
const defaults = { theme: "light", fontSize: 14, lang: "en" };
const userPrefs = { theme: "dark", fontSize: 18 };
 
const settings = Object.assign({}, defaults, userPrefs);
console.log(settings);
// { theme: "dark", fontSize: 18, lang: "en" }

Summary of Built-in Methods

MethodReturnsPurpose
Object.keys(obj)string[]Get all own enumerable property names
Object.values(obj)any[]Get all own enumerable property values
Object.entries(obj)[string, any][]Get all own enumerable [key, value] pairs
Object.fromEntries(arr)objectCreate an object from [key, value] pairs
Object.assign(target, ...sources)objectCopy properties from sources into target
Object.freeze(obj)objectPrevent all property changes
Object.seal(obj)objectPrevent adding/deleting, allow updates
Object.getPrototypeOf(obj)`objectnull`

Practical Example: Form Validator

Here is a real-world example combining multiple method patterns:

javascriptjavascript
const FormValidator = {
  rules: {},
 
  addRule(field, validator, message) {
    if (!this.rules[field]) this.rules[field] = [];
    this.rules[field].push({ validator, message });
    return this;
  },
 
  required(field, message) {
    return this.addRule(field, value => value !== "" && value != null, message || `${field} is required`);
  },
 
  minLength(field, min, message) {
    return this.addRule(field, value => String(value).length >= min, message || `${field} must be at least ${min} characters`);
  },
 
  isEmail(field, message) {
    return this.addRule(field, value => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value), message || `${field} must be a valid email`);
  },
 
  validate(data) {
    const errors = {};
 
    for (const [field, rules] of Object.entries(this.rules)) {
      for (const rule of rules) {
        if (!rule.validator(data[field])) {
          if (!errors[field]) errors[field] = [];
          errors[field].push(rule.message);
        }
      }
    }
 
    return {
      valid: Object.keys(errors).length === 0,
      errors
    };
  },
 
  reset() {
    this.rules = {};
    return this;
  }
};
 
FormValidator
  .required("name")
  .minLength("name", 2, "Name must be at least 2 characters")
  .required("email")
  .isEmail("email");
 
const result = FormValidator.validate({
  name: "A",
  email: "invalid"
});
 
console.log(result);
// { valid: false, errors: { name: ["Name must be at least 2 characters"], email: ["email must be a valid email"] } }

Best Practices

  1. Use method shorthand (greet() {}) as the default for defining methods on object literals
  2. Never use arrow functions as top-level object methods; they break this binding
  3. Return this from setter methods to enable chaining
  4. Prefer Object.keys/values/entries over for...in loops because they skip inherited properties automatically
  5. Keep methods focused: each method should do one thing and have a descriptive name

Common Mistakes to Avoid

Losing this When Extracting Methods

javascriptjavascript
const counter = {
  count: 0,
  increment() {
    this.count++;
  }
};
 
// WRONG: extracting loses `this`
const inc = counter.increment;
inc(); // `this` is undefined in strict mode
 
// CORRECT: bind the method
const boundInc = counter.increment.bind(counter);
boundInc(); // Works: this.count becomes 1
Rune AI

Rune AI

Key Insights

  • Method shorthand: Use greet() {} over greet: function() {} in object literals for cleaner syntax
  • this binding: this inside a method refers to the object that called it, not where it was defined
  • Arrow functions: Never use as top-level object methods; they inherit outer this and break method behavior
  • Method chaining: Return this from methods to enable fluent obj.a().b().c() call chains
  • Built-in methods: Object.keys, Object.values, and Object.entries convert objects to arrays for iteration
RunePowered by Rune AI

Frequently Asked Questions

What is the difference between a function and a method?

method is a function that is stored as a property of an object. When you call `user.greet()`, `greet` is a method because it belongs to `user`. When you call `greet()` on its own, it is a standalone function. The key difference is that methods have access to `this`, which refers to the object they belong to.

Can I use [default parameters](/tutorials/programming-languages/javascript/how-to-use-default-parameters-in-js-functions) in object methods?

Yes. Method shorthand supports all the same features as regular functions, including default parameters, rest parameters, and [destructuring](/tutorials/programming-languages/javascript/javascript-array-destructuring-complete-tutorial). For example: `addItem(name, qty = 1) { ... }` works perfectly in an object literal.

Should I use Object.keys or for...in to iterate objects?

Prefer `Object.keys()` (or `Object.entries()`) because they return only the object's own enumerable properties. A `for...in` loop also iterates over inherited properties from the prototype chain, which can introduce unexpected keys unless you guard with `hasOwnProperty()`.

Why does `this` change when I pass a method as a callback?

JavaScript determines `this` at call time, not at definition time. When you pass a method as a callback (like `setTimeout(user.greet, 1000)`), the method is called without the object context, so `this` becomes `undefined` (strict mode) or the global object. Use `.bind(user)`, a wrapper [arrow function](/tutorials/programming-languages/javascript/javascript-arrow-functions-a-complete-es6-guide), or call directly in the callback to preserve `this`.

What are getter and setter methods?

Getters and setters are special methods defined with `get` and `set` keywords that look like normal property access but execute code behind the scenes. `get fullName()` lets you access `user.fullName` without parentheses. They provide computed or validated property access while maintaining a clean interface.

Conclusion

Object methods combine data and behavior in a single structure. Shorthand method syntax keeps definitions clean, this binding tells the method which object it operates on, and method chaining creates fluent APIs. The built-in Object.keys, Object.values, and Object.entries methods transform objects into arrays for easy iteration and transformation. Mastering these patterns gives you the foundation for working with JavaScript's object-oriented features and building well-organized, maintainable code.