
Accessing properties on objects using dot notation is the most simpler and common way in JavaScript. It’s concise, readable, and works well when you know the exact name of the property at the time you write your code.
When you have an object like this:
const user = {
name: "Alice",
age: 30,
city: "New York"
};
You can access the name property simply by writing:
console.log(user.name); // Outputs: Alice
This syntax tells JavaScript to look inside the user object and retrieve the value associated with the key name.
Dot notation is not just for reading values; you can also use it to assign new values or add properties:
user.age = 31; user.country = "USA"; console.log(user.age); // 31 console.log(user.country); // USA
It’s important to note that the property name after the dot has to be a valid identifier—letters, digits, underscores, and dollar signs are allowed, but it cannot start with a digit or contain spaces or special characters.
This means you can’t write user.123name or user.first name without causing syntax errors. This limitation is why sometimes bracket notation becomes necessary, but if you can use dot notation, prefer it for clarity and simplicity.
Another subtlety is that dot notation accesses properties literally. If you do:
const key = "city"; console.log(user.key);
You won’t get the value “New York.” Instead, JavaScript looks for a property named “key,” which probably doesn’t exist, so it returns undefined. To use a variable as the property name, bracket notation is required, but more on that later.
Dot notation also works well with nested objects. For example, if you want to access a property within a deeper object:
const settings = {
display: {
resolution: "1080p",
brightness: 70
}
};
console.log(settings.display.resolution); // 1080p
Chaining dots lets you reach deeper properties directly, which keeps your code clean and expressive.
One edge case to keep in mind: properties defined with reserved words or unusual characters can still be accessed via dot notation if they conform to identifier rules, but if they don’t, bracket notation is mandatory. For instance:
const obj = {
"default": 42,
"foo-bar": 7
};
console.log(obj.default); // 42
console.log(obj["foo-bar"]); // 7
Trying obj.foo-bar would be a syntax error because of the hyphen.
Dot notation is your go-to for known, valid property names. It’s terse, readable, and the best choice for most situations where properties have static names. When you start dealing with dynamic keys or keys that don’t fit JavaScript’s identifier rules, you’ll need to switch to bracket notation, which we’ll see next.
EONCHARM Universal Remote Control for All Samsung TV Compatible with All Samsung LCD LED HDTV 3D Smart TVs Models
$5.60 (as of June 3, 2026 23:09 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Use bracket notation for dynamic keys
Bracket notation lets you use expressions to access or set properties dynamically. Instead of writing the property name literally, you provide a string or a value that evaluates to a string inside square brackets.
Consider this example:
const key = "city"; console.log(user[key]); // Outputs: New York
Here, key is a variable holding the string "city". Using bracket notation, JavaScript evaluates user[key] as user["city"], returning the expected value.
Bracket notation is indispensable when property names aren’t known until runtime. For example, if you receive user input or iterate over a list of keys, bracket notation lets you access properties flexibly:
const fields = ["name", "age", "city"];
fields.forEach(field => {
console.log(user[field]);
});
This prints each property value without hardcoding the property names.
Besides strings, bracket notation also accepts expressions that coerce to strings:
const index = 1;
const arr = ["first", "second", "third"];
const obj = {
prop1: "Value 1",
prop2: "Value 2"
};
console.log(arr[index]); // second
console.log(obj["prop" + index]); // Value 2
Notice how "prop" + index builds the property name dynamically. You can combine variables, literals, and functions to compute keys on the fly.
Bracket notation also allows accessing properties with names that contain spaces, special characters, or start with digits—cases where dot notation fails:
const weird = {
"first name": "Bob",
"123": "numbers",
"@special!": true
};
console.log(weird["first name"]); // Bob
console.log(weird["123"]); // numbers
console.log(weird["@special!"]); // true
Trying to access these with dot notation would cause syntax errors or unexpected behavior.
It’s also useful for setting properties dynamically. You can assign new values or create properties whose names come from variables:
const propName = "score"; user[propName] = 95; console.log(user.score); // 95
This pattern is common in situations like building objects from form inputs or API responses.
One subtlety is that if you use non-string keys, JavaScript coerces them to strings. For example:
const obj = {};
obj[42] = "The answer";
console.log(obj["42"]); // The answer
Here, the number 42 becomes the string "42". This can cause confusion if you expect keys to be numbers, but JavaScript object keys are always strings (or symbols, which are different).
Keep in mind that bracket notation cannot be used to access private class fields or symbols directly without the symbol reference. For normal properties, though, it offers unmatched flexibility to work with dynamic keys or irregular property names. It’s the tool you reach for when dot notation is too rigid or impractical.
Using bracket notation can sometimes make your code less readable if overused with complex expressions, so balance clarity with flexibility. For example, that’s harder to follow:
const prefix = "user_"; const id = 123; console.log(data[prefix + id + "_name"]);
But it’s often unavoidable in data-driven scenarios or when property names depend on user input or external sources. The key is to keep your expressions simple and document your code when the property keys become non-obvious.
Next, we’ll explore common pitfalls when accessing properties, including what happens when the property doesn’t exist, how to avoid runtime errors, and the nuances of truthy and falsy values in property lookup.
Understand property access pitfalls and how to avoid them
When working with object properties in JavaScript, it’s crucial to understand some common pitfalls that can lead to unexpected behavior. One of the most frequent issues arises when attempting to access a property that doesn’t exist on an object.
For instance, if you try to access a property that hasn’t been defined, JavaScript will return undefined. This can lead to errors later in your code if you assume that the property exists:
const user = {
name: "Alice"
};
console.log(user.age); // undefined
console.log(user.age + 1); // NaN
In this example, trying to add 1 to user.age results in NaN because undefined is treated as a numeric value. Always check if a property exists before performing operations on it:
if (user.age !== undefined) {
console.log(user.age + 1);
} else {
console.log("Age is not defined.");
}
Another pitfall is the difference between undefined and null. While undefined indicates a missing property, null is an explicit assignment that indicates no value. Confusing these can lead to bugs:
const settings = {
theme: null
};
console.log(settings.theme); // null
console.log(settings.language); // undefined
In this case, both properties are being accessed, but one is explicitly set to null while the other is simply missing. Make sure to handle both cases appropriately in your logic.
Another subtle issue arises with prototype properties. If you try to access a property this is not on the object itself but exists on its prototype chain, it can lead to confusion:
const animal = {
species: "Cat"
};
const dog = Object.create(animal);
dog.name = "Buddy";
console.log(dog.name); // Buddy
console.log(dog.species); // Cat
console.log(dog.hasOwnProperty('species')); // false
In this example, dog has its own property name, but species comes from its prototype animal. Using hasOwnProperty helps determine if the property is a direct property of the object.
Moreover, be cautious about properties that might be shadowed. If you define a property on an object that has the same name as a prototype property, the object’s property will take precedence:
const vehicle = {
type: "Car"
};
const bike = Object.create(vehicle);
bike.type = "Mountain Bike";
console.log(bike.type); // Mountain Bike
console.log(bike.type === vehicle.type); // false
Here, the type property on bike shadows the one on vehicle. This can lead to unexpected behavior if you’re not aware of the property hierarchy.
Lastly, remember that JavaScript uses “truthy” and “falsy” values when evaluating expressions. An access operation that returns a falsy value can lead to misleading assumptions about the property’s existence:
const user = {
isActive: false
};
if (user.isActive) {
console.log("User is active.");
} else {
console.log("User is not active."); // This will be logged
}
In this case, false is a falsy value, so the condition fails even though the property exists. Be careful when relying on truthy evaluations to check for the existence of properties.
To guard against these pitfalls, you can use optional chaining introduced in ES2020, which allows safe property access without throwing an error when a property doesn’t exist:
const user = null; console.log(user?.name); // undefined
Using the optional chaining operator ?. returns undefined instead of throwing an error when attempting to access name on a null object.
Understanding these nuances of property access not only helps in writing safer code but also in debugging issues that arise from unexpected property states. Always be mindful of the structure of your objects and the potential for missing or shadowed properties, as well as the implications of truthy and falsy evaluations.
