JS Objects: Dot Notation vs Bracket Notation
Understand the key differences between dot notation and bracket notation for JavaScript object property access. Learn when to use each syntax with real-world examples, performance tips, and common pitfalls.
JavaScript gives you two ways to access object properties: dot notation (obj.key) and bracket notation (obj["key"]). Both retrieve the same values, but they differ in flexibility, syntax rules, and use cases. Many beginners use them interchangeably without understanding when each one is appropriate, which leads to bugs when property names contain special characters or come from variables.
This guide explains the exact differences, shows when each notation is required, and provides real-world patterns for both.
Dot Notation Syntax
Dot notation uses a period between the object name and the property name. The property name must be a valid JavaScript identifier:
const car = {
make: "Toyota",
model: "Camry",
year: 2024,
color: "silver"
};
console.log(car.make); // "Toyota"
console.log(car.model); // "Camry"
console.log(car.year); // 2024Valid Identifier Rules
A property name works with dot notation only if it follows JavaScript identifier rules:
| Rule | Valid Examples | Invalid Examples |
|---|---|---|
Starts with letter, _, or $ | name, _id, $price | 2name, -key |
Contains letters, digits, _, $ | firstName, item_2, $total | first-name, item 2 |
| Not a reserved word (mostly) | status, type, value | Works but avoid class, return |
const obj = {
name: "Alice", // Valid: dot works
_id: 42, // Valid: starts with underscore
$price: 9.99, // Valid: starts with dollar sign
item2: "widget" // Valid: digit not at start
};
console.log(obj.name); // "Alice"
console.log(obj._id); // 42
console.log(obj.$price); // 9.99Bracket Notation Syntax
Bracket notation uses square brackets with a string expression. Any valid string (or expression that evaluates to a string) works inside the brackets:
const car = {
make: "Toyota",
model: "Camry",
year: 2024,
"fuel-type": "hybrid",
"0-60mph": "7.5s"
};
console.log(car["make"]); // "Toyota"
console.log(car["fuel-type"]); // "hybrid"
console.log(car["0-60mph"]); // "7.5s"Dynamic Property Access
The key advantage of bracket notation is using variables and expressions to determine which property to access:
const product = {
name: "Laptop",
price: 999,
category: "electronics",
brand: "TechBrand"
};
function getField(obj, fieldName) {
return obj[fieldName]; // Dynamic access
}
console.log(getField(product, "name")); // "Laptop"
console.log(getField(product, "price")); // 999
console.log(getField(product, "category")); // "electronics"
// With computed keys
const prefix = "user";
const data = {
userName: "alice",
userAge: 28,
userRole: "admin"
};
console.log(data[prefix + "Name"]); // "alice"
console.log(data[prefix + "Age"]); // 28
console.log(data[`${prefix}Role`]); // "admin"Side-by-Side Comparison
| Feature | Dot Notation | Bracket Notation |
|---|---|---|
| Syntax | obj.property | obj["property"] |
| Dynamic keys (variables) | Not supported | obj[variable] |
| Special characters | Not supported | obj["my-key"] |
| Numbers as keys | Not supported | obj["123"] |
| Computed expressions | Not supported | obj["key" + num] |
| Readability | Cleaner, shorter | More verbose |
| Common use | Static, known keys | Dynamic or special keys |
| Setting properties | obj.key = value | obj["key"] = value |
When Dot Notation Fails
There are specific situations where dot notation simply cannot work and bracket notation is required:
Property Names with Hyphens or Spaces
const apiResponse = {
"content-type": "application/json",
"x-request-id": "abc-123",
"rate limit": 100,
"max-retries": 3
};
// Dot notation fails on these
// apiResponse.content-type → interpreted as apiResponse.content minus type
// apiResponse.rate limit → SyntaxError
// apiResponse.x-request-id → interpreted as subtraction
// Bracket notation works perfectly
console.log(apiResponse["content-type"]); // "application/json"
console.log(apiResponse["x-request-id"]); // "abc-123"
console.log(apiResponse["rate limit"]); // 100Property Names Starting with Numbers
const rankings = {
"1st": "Alice",
"2nd": "Bob",
"3rd": "Charlie"
};
// Dot notation: SyntaxError
// rankings.1st
// Bracket notation: works fine
console.log(rankings["1st"]); // "Alice"
console.log(rankings["2nd"]); // "Bob"Property Names from Variables
const settings = {
theme: "dark",
fontSize: 16,
language: "en"
};
const userChoice = "theme";
// WRONG: looks for a property literally named "userChoice"
console.log(settings.userChoice); // undefined
// CORRECT: evaluates the variable to get "theme"
console.log(settings[userChoice]); // "dark"Real-World Patterns Using Bracket Notation
Building Objects from Form Data
function formDataToObject(fields) {
const result = {};
for (const field of fields) {
result[field.name] = field.value; // Dynamic key assignment
}
return result;
}
const formFields = [
{ name: "firstName", value: "Alice" },
{ name: "lastName", value: "Johnson" },
{ name: "email", value: "alice@example.com" }
];
const formData = formDataToObject(formFields);
console.log(formData);
// { firstName: "Alice", lastName: "Johnson", email: "alice@example.com" }Config Lookup Tables
const errorMessages = {
404: "Page not found",
500: "Internal server error",
403: "Access forbidden",
401: "Authentication required"
};
function getErrorMessage(statusCode) {
return errorMessages[statusCode] || "Unknown error";
}
console.log(getErrorMessage(404)); // "Page not found"
console.log(getErrorMessage(500)); // "Internal server error"
console.log(getErrorMessage(999)); // "Unknown error"Property Name Transformation
const apiData = {
first_name: "Alice",
last_name: "Johnson",
birth_date: "1998-03-15",
phone_number: "555-0100"
};
// Convert snake_case to camelCase
function snakeToCamel(str) {
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
}
const camelData = {};
for (const key of Object.keys(apiData)) {
camelData[snakeToCamel(key)] = apiData[key];
}
console.log(camelData);
// { firstName: "Alice", lastName: "Johnson", birthDate: "1998-03-15", phoneNumber: "555-0100" }Iterating with for...in Loops
const userStats = {
posts: 142,
followers: 2840,
following: 386,
likes: 9200
};
for (const key in userStats) {
// Bracket notation is the ONLY way to access properties dynamically in a loop
console.log(`${key}: ${userStats[key]}`);
}
// posts: 142
// followers: 2840
// following: 386
// likes: 9200Real-World Patterns Using Dot Notation
Object Method Chaining
Dot notation provides clean, readable method calls on objects:
class QueryBuilder {
constructor(table) {
this.table = table;
this.conditions = [];
this.sortField = null;
this.limitCount = null;
}
where(condition) {
this.conditions.push(condition);
return this;
}
orderBy(field) {
this.sortField = field;
return this;
}
limit(count) {
this.limitCount = count;
return this;
}
build() {
let query = `SELECT * FROM ${this.table}`;
if (this.conditions.length > 0) {
query += ` WHERE ${this.conditions.join(" AND ")}`;
}
if (this.sortField) query += ` ORDER BY ${this.sortField}`;
if (this.limitCount) query += ` LIMIT ${this.limitCount}`;
return query;
}
}
const query = new QueryBuilder("users")
.where("age > 18")
.where("active = true")
.orderBy("name")
.limit(10)
.build();
console.log(query);
// "SELECT * FROM users WHERE age > 18 AND active = true ORDER BY name LIMIT 10"Accessing Nested API Response Data
const response = {
status: 200,
data: {
user: {
name: "Alice",
profile: {
avatar: "alice.jpg",
bio: "Developer"
}
}
}
};
// Clean, readable nested access
const avatar = response.data.user.profile.avatar;
console.log(avatar); // "alice.jpg"Best Practices
- Default to dot notation for known, static property names. It is shorter, cleaner, and easier to read.
- Switch to bracket notation when working with dynamic keys, variables, or special-character property names.
- Avoid bracket notation with static strings when dot notation works. Writing
user["name"]instead ofuser.nameadds unnecessary characters. - Use optional chaining (
?.) with both notations when accessing properties on potentially null or undefined values. - Prefer destructuring when extracting multiple properties at once. It is more readable than multiple dot or bracket accesses.
// Good: dot notation for known keys
const name = user.name;
const age = user.age;
// Better: destructuring for multiple properties
const { name, age, email } = user;
// Good: bracket notation for dynamic keys
const value = settings[userSelectedField];
// Good: optional chaining for potentially missing data
const city = user?.address?.city;Common Mistakes to Avoid
Using Dot Notation with Variables
const key = "name";
const user = { name: "Alice" };
// WRONG: looks for literal property "key"
console.log(user.key); // undefined
// CORRECT: evaluates variable to "name"
console.log(user[key]); // "Alice"Forgetting Quotes in Bracket Notation
const user = { name: "Alice" };
const name = "different value";
// Without quotes: uses the VARIABLE named 'name'
console.log(user[name]); // undefined (looking for property "different value")
// With quotes: uses the STRING "name"
console.log(user["name"]); // "Alice"Rune AI
Key Insights
- Dot notation: Best for static, known property names that follow valid identifier rules
- Bracket notation: Required for dynamic keys, special characters, numbers, and computed expressions
- Variable access: Only bracket notation can use variables to determine which property to read
- Both return undefined: Accessing nonexistent properties returns
undefinedwith either notation - Default to dot: Use dot notation by default and switch to brackets only when necessary
Frequently Asked Questions
Is dot notation faster than bracket notation?
Can I use bracket notation for everything and skip dot notation?
How does property access work with [arrays](/tutorials/programming-languages/javascript/what-is-an-array-in-javascript-a-complete-guide)?
What happens if I access a property that does not exist?
Can bracket notation use non-string values?
Conclusion
Dot notation and bracket notation both access object properties, but they serve different roles. Dot notation is your everyday choice for static, known property names because of its clean, readable syntax. Bracket notation steps in when you need dynamic access, computed keys, or property names with special characters. Most JavaScript code uses dot notation about 80% of the time, switching to bracket notation only when the situation requires it.
More in this topic
OffscreenCanvas API in JS for UI Performance
Master the OffscreenCanvas API to offload rendering from the main thread. Covers worker-based 2D and WebGL rendering, animation loops inside workers, bitmap transfer, double buffering, chart rendering pipelines, image processing, and performance measurement strategies.
Advanced Web Workers for High Performance JS
Master Web Workers for truly parallel JavaScript execution. Covers dedicated and shared workers, structured cloning, transferable objects, SharedArrayBuffer with Atomics, worker pools, task scheduling, Comlink RPC patterns, module workers, and performance profiling strategies.
JavaScript Macros and Abstract Code Generation
Master JavaScript code generation techniques for compile-time and runtime metaprogramming. Covers AST manipulation, Babel plugin authorship, tagged template literals as macros, code generation pipelines, source-to-source transformation, compile-time evaluation, and safe eval alternatives.