In languages such as Java and C++, you can declare and initialize variables, also known as fields or attributes, within the class body.
In JavaScript, the most common way to declare fields is within the class constructor:
class Account {
constructor() {
this.balance = 0;
}
}
const acc = new Account();
console.log(acc); // {"balance":0}
This approach is beneficial when you want to allow clients to instantiate a class with custom values for initializing the fields:
class Account {
constructor(balance) {
this.balance = balance;
}
}
const acc = new Account(10);
console.log(acc); // {"balance":10}
Alternatively, you can initialize the fields in the class body:
class Account {
balance = 0;
constructor(name) {
this.name = name;
}
}
const acc1 = new Account("Jim");
const acc2 = new Account("John");
console.log(acc1); // {"balance":0,"name":"Jim"}
console.log(acc2); // {"balance":0,"name":"John"}
However, for improved readability, it’s advisable to always initialize your class attributes within the constructor.
You can initialize a field and use the constructor to override its initial value. Here’s an example:
class Account {
balance = 0;
constructor(balance) {
if (balance) this.balance = balance;
}
}
const acc1 = new Account();
const acc2 = new Account(10);
console.log(acc1); // {"balance":0}
console.log(acc2); // {"balance":10}
You can also use parameters with default values to achieve the same result:
class Account {
constructor(balance = 0) {
this.balance = balance;
}
}
const acc1 = new Account();
const acc2 = new Account(10);
console.log(acc1); // {"balance":0}
console.log(acc2); // {"balance":10}
You are not restricted to declaring fields only within the constructor or class body. They can be declared within any method.
class Publication {
setTitle(title) {
this.title = title;
}
setAuthor(author) {
this.author = author;
}
getTitle() {
return this.title;
}
getAuthor() {
return this.author;
}
print() {
console.log(this.getTitle() + " by " + this.getAuthor());
}
}
const publication = new Publication();
publication.setTitle("CS280 Notes");
publication.setAuthor("Ali Madooei");
publication.print(); // CS280 Notes by Ali Madooei
Though assigning properties within any method is possible, it’s generally not recommended. It could lead to unpredictable class structures and make the code more challenging to understand.
Private fields can be declared using a hash #
prefix. They can only be accessed from within the class that defines them:
class Account {
#balance = 0;
deposit(amount) {
this.#balance += amount
}
print() {
console.log(this.#balance)
}
}
const acc = new Account();
acc.deposit(10);
console.log(acc); // {}
acc.print(); // 10
Here, #balance
is a private field. It can’t be accessed from outside the Account
class. Attempting to access #balance
outside of class methods will result in a syntax error. This is beneficial for encapsulation, where a class’s internal details are hidden from the external world.
Methods can be declared in the class body or within the constructor. Here’s an example of declaring a method in the class body:
class Account {
balance = 0;
deposit(amount) {
this.balance += amount;
}
withdraw(amount) {
this.balance -= amount;
}
print() {
console.log(this.balance);
}
}
In this example, deposit
, withdraw
, and print
are methods of the Account
class. They can be invoked on an instance of the Account
class:
const acc = new Account();
acc.deposit(10);
acc.withdraw(5);
acc.print(); // 5
You can also declare methods within the constructor:
class Account {
constructor() {
this.balance = 0;
this.deposit = function(amount) {
this.balance += amount;
}
this.withdraw = function(amount) {
this.balance -= amount;
}
this.print = function() {
console.log(this.balance);
}
}
}
In this example, deposit
, withdraw
, and print
are declared within the constructor. They can be invoked in the same way as the previous example. In a situation like this, you can make clever use of closures to create private methods or fields. Here is an example where balance
is a private field:
class Account {
constructor() {
let balance = 0;
this.deposit = function(amount) {
balance += amount;
}
this.withdraw = function(amount) {
balance -= amount;
}
this.print = function() {
console.log(balance);
}
}
}
You can also use arrow functions to declare methods (inside the constructor or class body):
class Account {
constructor() {
this.balance = 0;
this.deposit = (amount) => {
this.balance += amount;
}
this.withdraw = (amount) => {
this.balance -= amount;
}
}
print = () => {
console.log(this.balance);
}
}
Methods can be declared pretty much anywhere in a class. However, it’s recommended to declare them in the class body for better readability and maintainability. Moreover, you can make any of the methods private by using the #
prefix. This way, the method can only be accessed from within the class that defines it.