Properties are the named values inside an object. This lesson covers everything you can do with them: read, add, change, delete, check, and loop through.
const pet = { name: "Biscuit", species: "dog" };
console.log(pet.name); // dot notation
console.log(pet["name"]); // bracket notation: key as a string
Both read the same property. Brackets are required in two situations:
// 1. The key is stored in a variable
let field = "species";
console.log(pet[field]); // "dog"
console.log(pet.field); // undefined (looks for a key literally named "field")
// 2. The key is not a valid identifier
const data = { "first name": "Ada" };
console.log(data["first name"]);
Assigning to a property that does not exist creates it. Assigning to one that does exist replaces its value:
const pet = { name: "Biscuit" };
pet.age = 3; // added
pet.name = "Biscuit Jr."; // changed
pet["color"] = "tan"; // added with brackets
console.log(pet);
delete pet.color;
console.log(pet.color); // undefined
delete works with brackets too, delete pet["color"], and it removes both the value and the key. (Setting a property to undefined is different: the key stays.)
Reading a missing property gives undefined, but so does a property that exists and holds undefined. To check for the key itself, use in or Object.hasOwn:
const user = { name: "Sam", nickname: undefined };
console.log("name" in user); // true
console.log("nickname" in user); // true (exists, value is undefined)
console.log("email" in user); // false
console.log(Object.hasOwn(user, "name")); // true
Reading a property of something that is undefined crashes. Optional chaining ?. stops and returns undefined instead:
const order = { id: 7 }; // no shipping info yet
// order.shipping.city; TypeError: Cannot read properties of undefined
console.log(order.shipping?.city); // undefined
console.log(order.shipping?.city ?? "Not set"); // "Not set"
?. pairs perfectly with ?? from the Logical lesson: try to read a nested value, and fall back to a default if any link in the chain is missing.
A property's value can be another object. Reach into it by chaining dots and brackets, in any mix:
const myObj = {
name: "John",
age: 30,
myCars: {
car1: "Ford",
car2: "BMW",
car3: "Fiat"
}
};
console.log(myObj.myCars.car2);
console.log(myObj.myCars["car2"]);
console.log(myObj["myCars"]["car2"]);
let p1 = "myCars";
let p2 = "car2";
console.log(myObj[p1][p2]); // both keys from variables
When a variable has the same name as the key you want, write it once:
const name = "Lee";
const age = 17;
const longWay = { name: name, age: age };
const shortWay = { name, age }; // same result
Brackets inside an object literal let a variable decide the key name:
const field = "score";
const result = { [field]: 95 };
console.log(result); // {score: 95}
const stock = { apples: 12, pears: 0, plums: 7 };
for (const key in stock) {
console.log(`${key}: ${stock[key]}`);
}
Three built-in helpers turn an object into arrays you can work with:
console.log(Object.keys(stock)); // ["apples", "pears", "plums"]
console.log(Object.values(stock)); // [12, 0, 7]
console.log(Object.entries(stock)); // [["apples", 12], ["pears", 0], ["plums", 7]]
console.log(Object.keys(stock).length); // 3 (how many properties)
// Total of all values
let total = 0;
for (const n of Object.values(stock)) total += n;
console.log(total); // 19
What does this log?
const car = { color: "red" };
const key = "color";
console.log(car.key, car[key]);
undefined red. car.key looks for a property literally named "key". car[key] uses the variable's value, "color".user.address may not exist. Which reads the zip code safely, with "none" as a fallback?
user.address.zip || "none"user.address?.zip ?? "none"user?.address.zip"zip" in user?. stops if address is missing, and ?? supplies the fallback. A crashes with a TypeError when there is no address; C still crashes at .zip; D checks the wrong object.What does this log?
const scores = { ana: 90, ben: 80, cy: 70 };
console.log(Object.keys(scores).length);
3. Object.keys gives an array of the three keys, and .length counts them.pet, logging it after each step?. and ?? to safely read user.address.zip when there is no addressObject.values