Understanding properties in JavaScript object-oriented programming is key to creating rich and meaningful objects. Properties represent the data or state associated with an object or a class. Simply put, if a JavaScript object were a character in a story, its properties would describe who it is — its name, age, color, or any attribute that defines it. Properties give life and individuality to objects, making them more than just empty shells.
In JavaScript, properties can take many forms. They might belong to individual objects (instance properties), to the class itself (static properties), or be hidden from the outside world (private properties). Properties can even be dynamic, using computed names or controlled through getter and setter functions. This article will explore all these aspects of properties, showing you exactly how to define and use them with clear, executable examples that bring these concepts to life.
Defining Instance Properties in Classes
Instance properties are the most common kind you encounter. These are properties tied to each object created by a class. When you create a new object, it carries its own copy of these properties, allowing each instance to have unique values.
Here’s a fun example with a Cat
class. Each cat has a name, age, and color. These values are set in the constructor, the special method that runs whenever we create a new cat.
class Cat {
constructor(name, age, color) {
this.name = name;
this.age = age;
this.color = color;
}
}
const lucy = new Cat("Lucy", 3, "orange");
const smokey = new Cat("Smokey", 5, "gray");
console.log(lucy.name); // Lucy
console.log(smokey.age); // 5
In this code, name
, age
, and color
are instance properties. The keyword this
refers to the object being created, and assigning values to this.name
and others creates those properties. Each cat instance remembers its own data.
Adding and Modifying Properties Outside the Constructor
JavaScript is flexible — you don’t need to define all properties inside the constructor. You can add new properties or change existing ones anytime after the object is created.
Let’s create a Dog
object and add a new property after creation:
class Dog {
constructor(name) {
this.name = name;
}
}
const buster = new Dog("Buster");
buster.breed = "Beagle"; // Adding new property after creation
console.log(buster.name); // Buster
console.log(buster.breed); // Beagle
buster.breed = "Labrador"; // Modifying property
console.log(buster.breed); // Labrador
Here, breed
was not defined in the constructor but was added directly to the buster
object later. This shows how properties are flexible and can be extended dynamically.
Using Static Properties
Static properties belong to the class itself, not to the instances. They are useful for values shared across all objects created by that class.
For example, consider a ChessPlayer
class with a static property to keep track of total players:
class ChessPlayer {
static totalPlayers = 0;
constructor(name) {
this.name = name;
ChessPlayer.totalPlayers++;
}
}
const harry = new ChessPlayer("Harry");
const ron = new ChessPlayer("Ron");
console.log(ChessPlayer.totalPlayers); // 2
In this example, totalPlayers
is a static property. It’s updated each time a new player is created. Notice you access it directly from the class ChessPlayer.totalPlayers
, not from the individual player objects.
Computed Property Names in Classes
Sometimes property names depend on variables or expressions. JavaScript allows computed property names using square brackets []
to dynamically define properties.
Here’s a Movie
class that uses a variable for a property name:
const dynamicProp = "rating";
class Movie {
constructor(title, value) {
this.title = title;
this[dynamicProp] = value; // Computed property name
}
}
const inception = new Movie("Inception", 9);
console.log(inception.title); // Inception
console.log(inception.rating); // 9
This approach is helpful when the property names are not known until runtime or depend on other variables.
Private Properties Using Modern JavaScript Syntax
JavaScript recently introduced private properties, which use the #
prefix. Private properties cannot be accessed directly outside the class, helping to hide internal data.
Let’s see a BankAccount
class with a private balance:
class BankAccount {
#balance;
constructor(initialBalance) {
this.#balance = initialBalance;
}
deposit(amount) {
this.#balance += amount;
}
getBalance() {
return this.#balance;
}
}
const account = new BankAccount(1000);
account.deposit(500);
console.log(account.getBalance()); // 1500
// console.log(account.#balance); // SyntaxError: Private field '#balance' must be declared in an enclosing class
Here, #balance
is a private property. It can only be read or changed via public methods like getBalance
and deposit
. Trying to access it directly causes an error, showing encapsulation in action.
Using Getters and Setters for Property Access Control
Getters and setters allow you to control how properties are accessed or changed, often wrapping private data with custom logic.
Consider a Player
class with a private _score
and public getter/setter for score:
class Player {
constructor(name) {
this.name = name;
this._score = 0;
}
get score() {
return this._score;
}
set score(value) {
if (value >= 0) {
this._score = value;
} else {
console.log("Score must be positive.");
}
}
}
const hermione = new Player("Hermione");
hermione.score = 10;
console.log(hermione.score); // 10
hermione.score = -5; // Score must be positive.
console.log(hermione.score); // 10 (unchanged)
Getters and setters provide a clean interface, allowing you to validate or transform values whenever properties are read or assigned.
Deleting Properties
JavaScript allows you to remove properties from objects using the delete
keyword.
For instance, here is a Car
object where we delete the color
property:
const car = {
make: "Toyota",
model: "Corolla",
color: "blue"
};
console.log(car.color); // blue
delete car.color;
console.log(car.color); // undefined
After delete car.color
, the color
property no longer exists on the car
object. This can be useful when you need to clean up or modify objects dynamically.
Conclusion
Properties form the backbone of object-oriented programming in JavaScript. They allow objects to carry meaningful information and define their individual identities. Whether you are working with instance properties unique to each object, static properties shared across a class, or private properties hidden from outside access, mastering how to define and manipulate properties is essential.
This article covered the full spectrum — from basic property definitions and dynamic property names to modern private properties and access control through getters and setters. Armed with this knowledge, you can bring your JavaScript classes and objects to life with clear, flexible, and powerful data structures.
References
If you want to learn more about JavaScript properties and object-oriented programming, these resources are excellent starting points:
- MDN Web Docs: Working with Objects
A comprehensive guide to JavaScript objects and their properties. - MDN Web Docs: Classes
Learn about JavaScript classes, constructors, and how properties fit in. - MDN Web Docs: Private Class Fields
Detailed explanation of private properties and their usage. - MDN Web Docs: Getters and Setters
Understand how to use getters and setters for property access control.