Repository navigation
Objects
Do not to think of Object as being like "Object-Oriented Programming," but instead think of it as a key/value based data structure.
const address = {
street1: '11 Broadway',
street2: '2nd Floor',
city: 'New York',
state: 'NY',
zipCode: 10004
};
address.street1;
// => "11 Broadway"
address.street2;
// => "2nd Floor"
address.city;
// => "New York"
address.state;
// => "NY"
address.zipCode;
// => 10004
address.country;
// => undefined
address['street1'];
// => "11 Broadway"
address['street2'];
// => "2nd Floor"
address['city'];
// => "New York"
address['state'];
// => "NY"
address['zipCode'];
// => 10004if you need to use non-standart keys:
const wildKeys = {
'Cash rules everything around me.': 'Wu',
'C.R.E.A.M.': 'Tang',
'Get the money.': 'For',
"$ $ bill, y'all!": 'Ever'
};You cannot access those properties with dot notation:
wildKeys.'Cash rules everything around me.';
// ERROR: Uncaught SyntaxError: Unexpected stringBut bracket notation works just fine:
wildKeys["$ $ bill, y'all!"];
// => "Ever"In order to access a property via dot notation, the key must follow the same naming rules applied to variables and functions. Under the hood all keys are strings.
const meals = {
breakfast: 'Oatmeal',
lunch: 'Caesar salad',
dinner: 'Chimichangas'
};
let mealName = 'lunch';
meals[mealName];
// => "Caesar salad"mealName = 'dinner';
// => "dinner"
meals.mealName;
// => undefinedCan also be used on creation:
const morningMeal = 'breakfast';
const middayMeal = 'lunch';
const eveningMeal = 'dinner';
const meals = {
[morningMeal]: 'French toast',
[middayMeal]: 'Personal pizza',
[eveningMeal]: 'Fish and chips'
};
meals;
// => { breakfast: "French toast", lunch: "Personal pizza", dinner: "Fish and chips" }const circle = {};
circle.radius = 5;
circle['diameter'] = 10;
circle;
// => { radius: 5, diameter: 10}keys must be unique. If the same key is used for multiple properties, only the final value will be retained.
const meals = {
breakfast: 'Avocado toast',
breakfast: 'Oatmeal',
breakfast: 'Scrambled eggs'
};
meals;
// => { breakfast: "Scrambled eggs" }Destructive!
function destructivelyUpdateObject (obj, key, value) {
obj[key] = value;
return obj;
}
const mondayMenu = {
fries: 'Sweet potato',
salad: 'Cobb'
};
const tuesdayMenu = destructivelyUpdateObject(mondayMenu, 'salad', 'Caesar');
// => { cheesePlate: { soft: "Chèvre", semiSoft: "Gruyère", hard: "Manchego" }, fries: "Sweet potato", salad: "Caesar" }
tuesdayMenu.salad;
// => "Caesar"
mondayMenu.salad;
// => "Caesar"Non-Destructive
with the ES2015 spread operator, we can copy all of the old menu Object's properties into a new Object:
function nondestructivelyUpdateObject(obj, key, value) {
const newObj = { ...obj };
newObj[key] = value;
return newObj;
}
const sundayMenu = nondestructivelyUpdateObject(tuesdayMenu, 'fries', 'Shoestring');
tuesdayMenu.fries;
// => "Sweet potato"
sundayMenu.fries;
// => "Shoestring"performance gains from non-destructive updates
Object.assign(initialObject, additionalObject, additionalObject, ...);Object.assign({ eggs: 3 }, { flour: '1 cup' });
// => { eggs: 3, flour: "1 cup" }
Object.assign({ eggs: 3 }, { chocolateChips: '1 cup', flour: '2 cups' }, { flour: '1/2 cup' });
// { eggs: 3, chocolateChips: "1 cup", flour: "1/2 cup" }In same key, the last key to be defined wins out.
This pattern allows us to rewrite the above destructivelyUpdateObject() function in a nondestructive way:
function nondestructivelyUpdateObject(obj, key, value) {
return Object.assign({}, obj, { [key]: value });
}
const recipe = { eggs: 3 };
const newRecipe = nondestructivelyUpdateObject(recipe, 'chocolate', '1 cup');
// => { eggs: 3, chocolate: "1 cup" }
newRecipe;
// => { eggs: 3, chocolate: "1 cup" }
recipe;
// => { eggs: 3 }It's important that we merge everything into a new, empty Object. Otherwise, we would be modifying the original Object. if you were to use Object.assign(obj, { [key]: value }); back to being destructive!
Note: For deep cloning, we need to use other alternatives because Object.assign() copies property values.
function nondestructivelyUpdateObject(oldObj, changes) {
return Object.assign({}, oldObj, changes);
}
const obj = { eggs: {uno: 1, due: 2}, tre: 3 };
const changes = { eggs: {uno: 1, quattro: 4}}
const newObj = nondestructivelyUpdateObject( obj, changes );
// => { eggs: {uno: 1, quattro: 4}, tre: 3 };
newObj;
// => { eggs: {uno: 1, quattro: 4}, tre: 3 };
// instead of:
// => { eggs: {uno: 1, quattro: 4, due: 2}, tre: 3 };
obj;
// => { eggs: {uno: 1, due: 2}, tre: 3 };const wednesdayMenu = {
cheesePlate: {
soft: 'Brie',
semiSoft: 'Fontina',
hard: 'Provolone'
},
fries: 'Sweet potato',
salad: 'Southwestern'
};
Object.keys(wednesdayMenu);
// => ["cheesePlate", "fries", "salad"]NOTE: The sequence in which keys are ordered in the returned Array is not consistent across browsers and should not be relied upon.
const wednesdayMenu = {
cheesePlate: {
soft: 'Brie',
semiSoft: 'Fontina',
hard: 'Provolone'
},
fries: 'Sweet potato',
salad: 'Southwestern'
};
delete wednesdayMenu.salad;
// => true
wednesdayMenu;
// => { cheesePlate: { soft: "Brie", semiSoft: "Fontina", hard: "Provolone" }, fries: "Sweet potato" }function updateDriverWithKeyAndValue(driver, key, value) {
return Object.assign({}, driver, { [key]: value })
}
function destructivelyUpdateDriverWithKeyAndValue(driver, key, value) {
driver[key] = value
return driver
}
function deleteFromDriverByKey(driver, key) {
const newDriver = { ...driver };
delete newDriver[key]
return newDriver
}
function destructivelyDeleteFromDriverByKey(driver, key) {
delete driver[key]
return driver
}typeof [];
// => "object"
const myArray = [];
myArray.summary = 'Empty array!';
myArray;
// => [summary: "Empty array!"]
myArray.push(2, 3, 5, 7);
// => 4
myArray;
// => [2, 3, 5, 7, summary: "Empty array!"]
myArray.length;
// => 4
myArray[0];
// => 2
myArray[myArray.length - 1];
// => 7const myArray = [];
myArray[0] = 'Will this be an `Object` property or an `Array` element?';
// => "Will this be an `Object` property or an `Array` element?"
// Moment of truth...
myArray.length;
// => 1myArray['0'] = 'What about this one?';
// => "What about this one?"
myArray.length;
// => 1
myArray;
// => ["What about this one?"]This is hitting on a fundamental truth: all keys in Objects and all indexes in Arrays are actually strings.
Under the hood the JavaScript engine automatically converts that to the string "0".
const myArray = [2, 3, 5, 7];
myArray['1'] = 'Hi';
// => "Hi"
myArray;
// => [2, "Hi", 5, 7]
myArray['01'] = 'Ho';
// => "Ho"
myArray;
// => [2, "Hi", 5, 7, 01: "Ho"]
myArray[01];
// => "Hi"
myArray['01'];
// => "Ho"
myArray.length;
// => 4
Object.keys(myArray);
// => ["0", "1", "2", "3", "01"]- For accessing elements in an Array, always use integers.
- Be wary of setting Object-style properties on an Array. There's rarely any reason to, and it's usually more trouble than it's worth.
- Remember that all Object keys, including Array indexes, are strings. This will really come into play when we learn how to iterate over Objects, so keep it in the back of your mind.