Skip to content

Object Properties

Properties are the fundamental building blocks of JavaScript objects. They associate a name (a key, which is a string or Symbol) with a value.

A property is a key-value pair associated with an object. The value can be a primitive (like a number, string, or boolean), another object, or a function (in which case, the property is often called a method).

A JavaScript object can be seen as a collection of properties. While property order for non-integer keys is generally maintained for an object’s own properties in modern JavaScript engines (since ES2015), it’s best not to rely on it for critical logic, especially for older environments or inherited properties.

Properties can typically be created, read, updated, and deleted. However, some properties (especially built-in ones or those defined with specific attributes) might be read-only or non-configurable.

There are two primary ways to access the property of an object:

  1. Dot Notation: objectName.propertyName Example: person.age

  2. Bracket Notation: objectName['propertyNameString'] or objectName[expression] (where expression evaluates to a string or Symbol representing the property name) Example: person['age'] or let prop = 'age'; person[prop]

Dot notation is generally preferred for its conciseness when the property name is a valid JavaScript identifier (starts with a letter, $ or _, contains letters, numbers, $ or _, and is not a reserved word). Bracket notation is more versatile: it must be used if the property name is not a valid identifier (e.g., 'first name', 'user-id') or if the property name is determined dynamically (e.g., stored in a variable).

const person = {
firstName: "Ada",
lastName: "Lovelace",
age: 36,
'country of birth': 'England'
};
// Using dot notation
console.log(`${person.firstName} is ${person.age} years old.`); // Output: Ada is 36 years old.
// Using bracket notation (necessary for 'country of birth')
let dynamicProperty = 'lastName';
console.log(`Her full name is ${person.firstName} ${person[dynamicProperty]}.`); // Output: Her full name is Ada Lovelace.
console.log(`Born in: ${person['country of birth']}`); // Output: Born in: England

Iterating Over Object Properties (for…in)

Section titled “Iterating Over Object Properties (for…in)”

The for...in statement iterates over the enumerable property keys (names) of an object. This includes an object’s own properties and properties inherited from its prototype chain.

for (const key in object) {
// It's crucial to check if the property is an own property
if (Object.hasOwnProperty.call(object, key)) {
// 'key' is the property name
// 'object[key]' is the property value
// Process own properties here
}
}

The code block within the for...in loop executes once for each enumerable property key found in the object or its prototype chain.

Looping through an object’s own properties:

const userProfile = {
username: "coder123",
email: "coder@example.com",
isActive: true
};
let profileDetails = "User Profile:\n";
for (const propKey in userProfile) {
if (Object.hasOwnProperty.call(userProfile, propKey)) {
profileDetails += `${propKey}: ${userProfile[propKey]}\n`;
}
}
console.log(profileDetails);
/* Output (order might vary for older engines):
User Profile:
username: coder123
email: coder@example.com
isActive: true
*/

For iterating only over an object’s own properties, modern alternatives like Object.keys(obj).forEach(), Object.values(obj).forEach(), or Object.entries(obj).forEach() (or using for...of with these methods) are often preferred for better control and clarity. See the chapter on Loops for more details.

You can add new properties to an existing object by assigning a value to a new property name using either dot notation or bracket notation.

Assume that the person object already exists - you can then give it new properties:

const person = {
firstName: "Grace",
lastName: "Hopper"
};
// Add a new property using dot notation
person.occupation = "Computer Scientist";
// Add a new property using bracket notation
person['date of birth'] = "December 9, 1906";
console.log(person.occupation); // Output: Computer Scientist
console.log(person['date of birth']); // Output: December 9, 1906
console.log(person);
// { firstName: 'Grace', lastName: 'Hopper', occupation: 'Computer Scientist', 'date of birth': 'December 9, 1906' }

Property names must be valid JavaScript identifiers if using dot notation. With bracket notation, property names are strings and can include reserved words or any characters. However, using reserved words as property names, even with bracket notation, can sometimes lead to confusion and is generally best avoided unless necessary.

The delete operator removes a property from an object. It returns true if the deletion was successful or if the property didn’t exist, and false if the property is non-configurable (cannot be deleted).

const book = {
title: "The Pragmatic Programmer",
author: "David Thomas, Andrew Hunt",
year: 1999
};
console.log(book.year); // Output: 1999
const wasDeleted = delete book.year;
console.log(wasDeleted); // Output: true
console.log(book.year); // Output: undefined (property no longer exists)
console.log(book); // { title: '...', author: '...' }
// Trying to delete a non-existent property
const nonExistentDeleted = delete book.nonExistentProperty;
console.log(nonExistentDeleted); // Output: true (still true as operation didn't fail)

The delete keyword removes both the value of the property and the property itself from the object.

After deletion, accessing the property will yield undefined. The property is completely removed from the object’s own properties.

The delete operator is specifically for object properties. It cannot delete variables declared with var, let, or const, nor can it delete standalone functions (unless they are properties of the global object, which is generally not recommended to modify).

Attempting to delete non-configurable properties (like many built-in properties of standard objects, e.g., Math.PI) will fail (return false) or throw a TypeError in strict mode. It’s generally not advisable to try to delete properties of predefined JavaScript objects unless you have a very specific reason and understand the consequences.

Beyond its name and value, each property in a JavaScript object has a set of internal attributes (also called descriptors) that define its behavior. The main attributes for data properties are:

  • value: The actual value associated with the property.
  • writable: A boolean. If true, the value of the property can be changed. If false, attempts to change the value are ignored (or throw an error in strict mode).
  • enumerable: A boolean. If true, the property will be listed during for...in loops and by Object.keys(). If false, it will be hidden from these operations.
  • configurable: A boolean. If true, the property can be deleted from the object, and its attributes (writable, enumerable, configurable, and value) can be changed. If false, the property cannot be deleted, and its enumerable and configurable attributes cannot be changed. writable can be changed from true to false when configurable is false, but not from false to true.

You can inspect these attributes using Object.getOwnPropertyDescriptor() and define or modify them using Object.defineProperty() or Object.defineProperties(). These methods provide fine-grained control over object properties.

Example using Object.defineProperty():

const myObj = {};
Object.defineProperty(myObj, 'readOnlyProp', {
value: "I cannot be changed!",
writable: false, // Not writable
enumerable: true, // Will show up in for...in and Object.keys()
configurable: false // Cannot be deleted or reconfigured
});
console.log(myObj.readOnlyProp); // I cannot be changed!
try {
myObj.readOnlyProp = "New Value"; // This will fail silently or throw in strict mode
} catch (e) {
console.error(e.message);
}
console.log(myObj.readOnlyProp); // Still "I cannot be changed!"
console.log(Object.keys(myObj)); // ['readOnlyProp']
const deleteStatus = delete myObj.readOnlyProp; // Fails because configurable is false
console.log(deleteStatus); // false (or throws in strict mode)
console.log(myObj.readOnlyProp); // Still "I cannot be changed!"

JavaScript objects have an internal link to another object called their prototype. When you try to access a property on an object, if the object itself doesn’t have that property (it’s not an ‘own’ property), JavaScript looks for it on the object’s prototype, then on the prototype’s prototype, and so on, up the prototype chain until the property is found or the chain ends (with null). These are called inherited properties.

The delete operator only works on an object’s own properties. It cannot delete properties inherited from the prototype chain. However, if you modify or delete a property directly on a prototype object, that change will be reflected in all objects that inherit from that prototype (unless they have their own overriding property with the same name).

function Dog(name) {
this.name = name; // Own property
}
Dog.prototype.species = "Canine"; // Property on the prototype
Dog.prototype.bark = function() { console.log('Woof!'); }; // Method on prototype
const buddy = new Dog("Buddy");
const lucy = new Dog("Lucy");
console.log(buddy.species); // Canine (inherited from Dog.prototype)
buddy.bark(); // Woof! (method inherited from Dog.prototype)
// 'delete' on an instance does not affect the prototype property for other instances
delete buddy.species; // This would only work if 'species' was an own property of 'buddy'.
// Since it's inherited, this operation has no effect on 'buddy.species'.
console.log(buddy.species); // Still Canine (it will re-lookup on prototype)
// If buddy had its own 'species' property, delete would remove that own property:
buddy.species = "Super Dog"; // buddy now has its own 'species' property, shadowing the prototype's.
console.log(buddy.species); // Super Dog
console.log(lucy.species); // Canine (lucy still inherits from Dog.prototype)
delete buddy.species; // Deletes buddy's own 'species' property
console.log(buddy.species); // Canine (now inherits from Dog.prototype again)
// To affect all instances, modify the prototype directly:
// delete Dog.prototype.species;
// console.log(buddy.species); // undefined (if deleted from prototype and no own property exists)
// console.log(lucy.species); // undefined