JavaScript Variable Naming: The Developer's Guide to camelCase

In JavaScript, name variables, functions, parameters and object properties in camelCase (cartTotal, fetchOrders), classes and React components in PascalCase (ShoppingCart), and save CONSTANT_CASE for values that are fixed for the life of the program (MAX_RETRIES). Google's and Airbnb's JavaScript style guides agree on that much, and JavaScript's own built-ins follow the same pattern.
The rest of this guide covers what the engine actually enforces, then the conventions layered on top, then the edge cases where teams disagree: which const values deserve capitals, private fields, acronyms, and snake_case data arriving from an API.
What JavaScript itself allows
The language's rules are short. An identifier starts with a letter, an underscore or a dollar sign, and later characters can also be digits. Letters aren't limited to ASCII: MDN's own example is the German word Früh. Names are case-sensitive, so total and Total are two different variables, and reserved words such as new, class and delete can't be used as variable names.
let total = 1;
let Total = 2; // a different variable
const café = "ok"; // Unicode letters are allowed
const $price = 9.99;
const _unused = null;
// const 2fast = true; // SyntaxError: can't start with a digit
// const new = 1; // SyntaxError: reserved wordProperty names are looser still: any string works if you quote it, which is how headers["Content-Type"] is possible. Everything beyond these rules is convention, which is exactly why it's worth agreeing on.
camelCase for variables, functions and properties
camelCase is the default for almost everything you name in JavaScript. Give values noun names and functions verb names, so a line reads like a sentence:
const orderCount = orders.length;
const isLoggedIn = Boolean(session);
const user = { firstName: "Ada", lastLogin: null };
function calculateShipping(order) {
// ...
}For booleans, an is, has or can prefix (isLoggedIn, hasAccess) answers the question "true or false of what?" before anyone has to ask. Google's guide uses the same prefixes for boolean getters (isFoo, hasFoo).
Google's guide also has a good rule on length: be as descriptive as you reasonably can, and don't abbreviate by deleting letters. errorCount and customerId pass; nErr and cstmrId don't. The guide's exception is a variable in scope for ten lines or fewer, such as the i in a short loop or the x in points.map((x) => x * 2).
Collections, counts and event handlers
A few patterns make names predictable. Use a plural for an array (users) and the singular for one item, so for (const user of users) reads naturally. Name a lookup object after its key (usersById) and a number after what it counts (userCount). In React, the docs describe a common convention for events: handlers are named handle plus the event (handleClick), and props that accept a handler start with on and a capital letter (onClick, onSave).
PascalCase for classes, constructors and components
Anything you construct with new gets PascalCase, and so does anything React renders as a component:
class ShoppingCart {
addItem(item) {
// ...
}
}
const cart = new ShoppingCart();
function OrderSummary({ order }) {
return <section>{order.id}</section>;
}For classes, it's convention. For React, it's required: the React docs say component names must start with a capital letter or they won't work, because JSX treats lowercase tags like <section> as plain HTML elements. In TypeScript, the same PascalCase goes on interfaces, type aliases and enums.
The built-ins model all of this. Constructors are PascalCase (Map, Promise, Date), methods are camelCase (Object.fromEntries, Array.prototype.flatMap), and fixed values are uppercase (Math.PI, Number.MAX_SAFE_INTEGER).
When to use CONSTANT_CASE (and when not to)
Constants cause the most confusion, because const doesn't mean "constant". It only stops the variable being reassigned; the array or object it points to can still change. Both big style guides reserve capitals for something stricter:
- Google: CONSTANT_CASE is for module-level values (and static properties) that are deeply immutable. Merely intending never to change an object isn't enough, and constants declared inside functions stay lowerCamelCase.
- Airbnb: uppercase is optional, and only for a value that's exported, declared with
const, and can be trusted (nested properties included) never to change. Uppercasing everyconstinside a file is unnecessary.
// Module level, never changes: capitals
export const MAX_UPLOAD_BYTES = 5 * 1024 * 1024;
export const ORDER_STATUS = Object.freeze({ PENDING: "pending", SHIPPED: "shipped" });
function visibleNames(items) {
const visible = items.filter((item) => !item.hidden); // const, but not a constant
const names = []; // const binding, mutable array
for (const item of visible) names.push(item.name);
return names;
}The guides part ways on the keys of an enum-like object. Google writes enum members in CONSTANT_CASE, as above; Airbnb prefers lowercase keys inside an uppercase export. Either is fine if the whole codebase does the same. One more catch: Object.freeze is shallow, so a frozen object can still hold a nested object that changes.
Private fields: use #, not an underscore
The old habit of marking "private" members with a leading underscore (this._count) is only a hint; anyone can still read and write the property. Airbnb's guide says not to use leading or trailing underscores for exactly that reason, and Google's TypeScript guide bans them as prefixes and suffixes too. Modern JavaScript has real private fields:
class Counter {
#count = 0;
increment() {
return ++this.#count;
}
}
const counter = new Counter();
counter.increment();
counter.count; // undefined
// counter.#count // SyntaxError outside the classAcronyms: userId or userID?
Google's rule is to treat acronyms as ordinary words: customerId, xmlHttpRequest, loadHttpUrl. Airbnb's is the opposite: keep an acronym all uppercase or all lowercase, as in SMSContainer or httpRequests. The browser itself can't decide, with XMLHttpRequest, innerHTML, getElementById and encodeURIComponent all in the same platform.
We'd pick Google's rule, because it's predictable, keeps word boundaries visible and converts cleanly between case styles. But consistency matters more than the choice. We compare every major guide's acronym rule in camelCase vs. PascalCase.
Handling snake_case data from APIs
APIs backed by Python, Ruby or a SQL database often hand you keys like first_name. Don't let them spread through your code. Rename at the point where the data arrives, and destructuring makes that a one-liner:
const response = await fetch("/api/users/42");
const { first_name: firstName, last_login: lastLogin } = await response.json();For whole payloads, write a small function for each direction that converts keys recursively, and call it in your API client; we walk through one in converting camelCase JSON to snake_case. For a one-off rename, our case converter turns last_login into lastLogin in one click.
Enforce it with ESLint
Two core ESLint rules cover most of this. camelcase flags underscores in the middle of names while ignoring all-caps constants and leading or trailing underscores. new-cap flags new used with a lowercase name, and a capitalized function called without new.
// eslint.config.js
export default [
{
rules: {
camelcase: ["error", { properties: "never" }],
"new-cap": "error",
},
},
];The properties: "never" option stops camelcase complaining about API fields such as data.first_name while still checking the variables you declare. In TypeScript projects, @typescript-eslint/naming-convention goes further, letting you set an allowed format for each kind of identifier: variables, functions, classes, type parameters and more. The full set of Google's rules is in the Google JavaScript Style Guide.
A JavaScript variable naming checklist
- camelCase for variables, functions, parameters, methods and properties.
- PascalCase for classes, constructors, React components, and TypeScript types, interfaces and enums.
- CONSTANT_CASE for module-level values that never change, not for every
const. #privatefields instead of underscore prefixes.- One acronym rule, written down in your contributing guide.
- snake_case API keys converted once, at the edge.


