JavaScript Object Methods
Methods are functions that belong to objects. They allow objects to have behavior, not just data. Understanding methods and the this keyword is essential for working with JavaScript objects.
Try It Yourself
Experiment with object methods and the this keyword:
// Object Methods and 'this' keyword
const person = {
firstName: "Alice",
lastName: "Smith",
age: 28,
// Method using 'this' to access object properties
getFullName() {
return this.firstName + " " + this.lastName;
},
// Method that modifies object state
haveBirthday() {
this.age++;
console.log("Happy birthday! Now " + this.age + " years old.");
},
// Method with parameters
greet(greeting) {
return greeting + ", I'm " + this.getFullName() + "!";
}
};
// Calling methods
console.log(person.getFullName());
console.log(person.greet("Hello"));
person.haveBirthday();
console.log("Current age:", person.age);Defining Methods
A method is a function stored as an object property. You can define methods in several ways:
const calculator = {
value: 0,
// Method defined with function keyword
add: function(n) {
this.value += n;
return this; // Enable chaining
},
// ES6 shorthand method (preferred)
subtract(n) {
this.value -= n;
return this;
},
reset() {
this.value = 0;
return this;
},
getValue() {
return this.value;
}
};
// Using the methods
calculator.add(10).subtract(3).add(5);
console.log(calculator.getValue()); // 12The this Keyword
Inside a method, this refers to the object that owns the method. It allows the method to access other properties and methods of the same object:
const user = {
name: "Alice",
age: 25,
// 'this' refers to the object calling the method
introduce() {
console.log("Hi, I'm " + this.name);
console.log("I'm " + this.age + " years old");
},
// Methods can call other methods via 'this'
celebrateBirthday() {
this.age++;
this.introduce();
}
};
user.introduce();
// Hi, I'm Alice
// I'm 25 years old
user.celebrateBirthday();
// Hi, I'm Alice
// I'm 26 years oldLosing this Context
Be careful when extracting methods from objects or using them as callbacks - you can lose the this context:
const person = {
name: "Alice",
greet() {
console.log("Hello, " + this.name);
}
};
// Normal method call - 'this' is the object
person.greet(); // "Hello, Alice"
// Extracting the method loses 'this' context!
const greetFunc = person.greet;
greetFunc(); // "Hello, undefined" (this is now global/undefined)
// Fix with bind()
const boundGreet = person.greet.bind(person);
boundGreet(); // "Hello, Alice"Arrow Functions and this
Arrow functions do NOT have their own this binding. They inherit this from the enclosing scope:
const person = {
name: "Alice",
// Regular method - works correctly
greetRegular() {
console.log("Regular: Hello, " + this.name);
},
// Arrow function - 'this' is NOT the object!
greetArrow: () => {
console.log("Arrow: Hello, " + this.name); // undefined!
}
};
person.greetRegular(); // "Regular: Hello, Alice"
person.greetArrow(); // "Arrow: Hello, undefined"
// Arrow functions inherit 'this' from enclosing scope
// In this case, 'this' is the global object (or undefined in strict mode)When Arrow Functions ARE Useful
Arrow functions are perfect for callbacks inside methods, where you want to preserve the outer this:
const team = {
name: "Development",
members: ["Alice", "Bob", "Carol"],
// Arrow functions are USEFUL in callbacks
printMembers() {
console.log("Team: " + this.name);
// Arrow function preserves 'this' from printMembers
this.members.forEach((member) => {
console.log(this.name + " member: " + member);
});
},
// Compare with regular function callback
printMembersBroken() {
console.log("Team: " + this.name);
// Regular function has its own 'this' (undefined in strict mode)
this.members.forEach(function(member) {
// console.log(this.name + " member: " + member); // Error!
});
}
};
team.printMembers();
// Team: Development
// Development member: Alice
// Development member: Bob
// Development member: Carol| Feature | Regular Function | Arrow Function |
|---|---|---|
| Own this binding | ||
| Good for methods | ||
| Good for callbacks | Needs binding | |
| Can use bind/call/apply | No effect | |
| Syntax | function() {} | () => {} |
call(), apply(), and bind()
These methods let you explicitly set what this refers to:
const person = {
name: "Alice"
};
function greet(greeting, punctuation) {
console.log(greeting + ", " + this.name + punctuation);
}
// call() - invoke with explicit 'this' and individual args
greet.call(person, "Hello", "!");
// "Hello, Alice!"
// apply() - same as call(), but args as array
greet.apply(person, ["Hi", "?"]);
// "Hi, Alice?"
// bind() - returns new function with 'this' permanently bound
const greetAlice = greet.bind(person);
greetAlice("Hey", ".");
// "Hey, Alice."
// bind() with preset arguments (partial application)
const sayHiToAlice = greet.bind(person, "Hi");
sayHiToAlice("!!!");
// "Hi, Alice!!!"- call() - Invoke immediately with individual arguments
- apply() - Invoke immediately with array of arguments
- bind() - Create a new function for later use
Getters and Setters
Getters and setters let you define computed properties that look like regular properties but execute code:
const circle = {
radius: 5,
// Getter - accessed like a property, but runs a function
get diameter() {
return this.radius * 2;
},
get area() {
return Math.PI * this.radius ** 2;
},
// Setter - assigned like a property, but runs a function
set diameter(value) {
this.radius = value / 2;
}
};
// Using getters (no parentheses)
console.log(circle.diameter); // 10
console.log(circle.area); // 78.54...
// Using setter
circle.diameter = 20;
console.log(circle.radius); // 10Method Chaining
Return this from methods to enable chaining multiple method calls:
const queryBuilder = {
query: "",
select(fields) {
this.query += "SELECT " + fields + " ";
return this; // Return 'this' to enable chaining
},
from(table) {
this.query += "FROM " + table + " ";
return this;
},
where(condition) {
this.query += "WHERE " + condition + " ";
return this;
},
build() {
return this.query.trim();
}
};
// Method chaining in action
const sql = queryBuilder
.select("name, email")
.from("users")
.where("age > 18")
.build();
console.log(sql);
// "SELECT name, email FROM users WHERE age > 18"Private Methods
You can create private methods using closures or ES2022 private fields:
// Using closures for private methods (pre-ES2022)
function createCounter() {
let count = 0; // Private variable
function increment() { // Private method
count++;
}
return {
add() {
increment();
return this;
},
getValue() {
return count;
}
};
}
const counter = createCounter();
counter.add().add().add();
console.log(counter.getValue()); // 3
// counter.increment(); // Error - not accessible
// ES2022 private fields and methods
class ModernCounter {
#count = 0; // Private field
#increment() { // Private method
this.#count++;
}
add() {
this.#increment();
return this;
}
getValue() {
return this.#count;
}
}Test Your Knowledge
Object Methods Quiz
5 questionsWhat does "this" refer to inside an object method?
Why should you NOT use arrow functions as object methods?
What is the difference between call() and apply()?
What does bind() return?
How do you define a getter in an object?
Coding Challenge
Build a bank account factory function with deposit, withdraw, getBalance, and transferTo methods. Methods should be chainable where appropriate.
// Challenge: Create a Bank Account object with methods
// Requirements:
// - deposit(amount) - add money, return the object for chaining
// - withdraw(amount) - remove money if sufficient funds, return object
// - getBalance() - return current balance
// - transferTo(otherAccount, amount) - transfer to another account
const createBankAccount = (initialBalance = 0) => {
// Your code here
};
// Test your implementation
const alice = createBankAccount(100);
const bob = createBankAccount(50);
alice.deposit(50).withdraw(30);
console.log("Alice balance:", alice.getBalance()); // 120
bob.deposit(100);
console.log("Bob balance:", bob.getBalance()); // 150
alice.transferTo(bob, 40);
console.log("Alice after transfer:", alice.getBalance()); // 80
console.log("Bob after transfer:", bob.getBalance()); // 190Summary
- Methods are functions stored as object properties
- this refers to the object that owns the method
- Arrow functions don't have their own this - avoid them for object methods
- Use bind() to permanently bind this to a function
- call() and apply() invoke functions with a specified this
- Getters and setters create computed properties
- Return this from methods to enable method chaining