CollectionsArraysBasic Array Operations (Methods)Higher Order Array MethodsObjectsDot vs Bracket NotationMethodsAdvanced ObjectsPrivacyGettersSettersFactory FunctionsCopyingIterationLooping Arrays, Breaking & ContinuingLooping Backwards and Loops in LoopsThe while Loopfor in and for of
Collections
- They are used to store collections of data. Programming is all about working with some data.
- They are stored as reference in memory meaning that
[] === []is false
Arrays
- Array is like a container where we can store values and later reference them
- They start with index
0and have alengthproperty
// Ist method (Array literal) const hosts = ['Cloudflare', 'Netlify', 'Vercel']; // IInd method const cars = new Array("Fisker", "Mustang", "Tesla"); // Accessing values console.log(hosts[0]); // "Cloudflare" console.log(cars.length) // 3 // Last element console.log(cars[cars.length - 1]) // "Lambo"
- Only primitive values are immutable, meaning that an array defined using
constwill still be mutable. But we can not reassign the value
- This is possible because of the way how JS stores values in memory
const startups = ["Cleao", "Phleebs", "Fugers", "Undercode"]; startups[1] = "Sezbania"; console.log(startups); // Cleao, Rovity, Fugers, Undercode startups = ["DuckDuckGo", "Fisker", "Phoenix"]; // Can't reassign
Basic Array Operations (Methods)
- Array methods allow us to do array operations
const friends = []; // Adding elements (returns the new length) friends.push('Benni', "Bob Ziroll"); // ["Benni", "Bob Ziroll"]; friends.unshift("Steve"); // ["Steve", "Benni", "Bob Ziroll"]; // Removing elements (returns deleted item) friends.pop(); // ["Steve", "Benni"]; friends.shift() // ["Benni"]; friends.indexOf('') // -1, gives the index friends.includes('Benni') // true, gives Boolean Array.concat() // Merge two arrays .slice() // Gets off part .splice(start, deleteCount, newElements) // Supports insertion & deletion .join(seperator) // Creates string
Higher Order Array Methods
These array methods takes in a callback function and performs some operation for each one of them
.forEach() // Invokes a function for each value .map() // Returns new array .filter() // Filters out based on some condition, if bool is true .some() // If any 1 value pass the test function .every() // If all the values pass the test .find() // The first value that pass the test .findIndex() // Index of the first value that pass the test /* The master .reduce() method The reduce() takes in a callback and gives an accumulator and the currentValue Whatever we return gets added to the current value [].reduce((acc, cv) => {}, starting value) */
Objects
- In Objects we give each of the value stored a name
- The names are also called as
keyorproperty
- There’s no order of properties, objects are unstructured and values can be accessed only using names
Dot vs Bracket Notation
- We can access values from an Object in two ways: dot and bracket notation syntax
- Both of them are operators. Dot is called Member Access & Brackets is called Computed Member Access
- Bracket notation accepts any expression so it’s good for computed name
- Can also be used to add values to the Object
// Accessing Values Object[expression] // Bracket Notation Object.key // Dot notation const teacher = { firstName: 'Jonas', lastName: 'Schmedtmann', age: 30, job: 'Teacher', friends: ["Michael", "Peter", "Steven"] } const key = "friends"; console.log(teacher.key); // undefined console.log(teacher[key]) // ["Michael", "Peter", "Steven"] // Object class methods Object.keys(), Object.entries(), Object.items()
Methods
- We can also store functions inside an object. Then it’s called a method of that Object
- Again, functions are just values, that’s why a method is also a property
- Arrays are also Objects as they also have methods
const person = { sayHi: function(){ console.log("Hello there"); } } person.sayHi(); // "Hello there" logged to the console
- The
thiskeyword refers to the calling object. Arrow functions don’t refer to the object and should be avoided as object methods.
const person = { firstName: 'Chak', birthYear: 2000, age: function(){ return 2024 - this.birthYear; // reference to Object } } person.age(); // gives 22
Advanced Objects
Privacy
- There are cases when we don’t want other code simply accessing and updating object’s properties. Other languages provide native support for this but in javascript we simply prepend an underscore (convention) signalling other developers that this is a private variable.
- Remember that we can still change a private property directly but we shouldn’t and this is left for getter and setter functions
const robot = { _energyLevel: 10, recharge() { this._energyLevel += 30; } }
Getters
- Getters are methods that get and return the internal properties of an object.
- They can perform some action on the data when getting a property
- Getters can return different values using conditionals
- In a getter we access the properties of the calling object using
this.
const person = { firstName: "John", lastName: "Doe", _language: "en", get lang() { if (!this._language){ // can check console.log("Language doesn't exist"); } else { return this._language; } } }; console.log(person.lang) // no need to invoke lang()
Setters
- Used to set values
const person = { firstName: "John", lastName: "Doe", _language: "en", get lang() { if (!this._language){ // can check console.log("Language doesn't exist"); } else { return this._language; } }, set lang(newLang) { this._language = newLang; } }; person.lang = 'Python'; // now person.lang should return Python
Factory Functions
- A factory function is a function that creates and returns an object, often used to avoid repeating code when generating multiple similar objects.
- Unlike constructor functions, they do not require the
newkeyword and do not use this to assign properties to the object being created.
- The function takes parameters to customize the new object's properties and can encapsulate complex logic for object creation.
// A factory function to create robot objects function createRobot(name) { return { name: name, talk: function() { console.log('My name is ' + name + ', the robot.'); } }; } // Create two different robots using the factory function const robo1 = createRobot('Chitti'); const robo2 = createRobot('Chitti 2.O'); robo1.talk(); // Output: My name is Chitti, the robot. robo2.talk(); // Output: My name is Chitti 2.O, the robot.
Copying
- We can use Object.assign(source, target) to create a shallow copy
- Otherwise use
JSON.parse(JSON.stringify(object));
- We can use
structuredClone()global function to create a deep copy
const originalObject = { name: "Alice", details: { age: 30, hobbies: ["coding", "reading"] }, date: new Date() }; const deepCopy = structuredClone(originalObject); // Modify the deep copy deepCopy.details.age = 31; deepCopy.details.hobbies.push("gaming"); console.log(originalObject.details.age); // Output: 30 (original is unchanged) console.log(deepCopy.details.age); // Output: 31 (copy is changed) console.log(originalObject.date instanceof Date); // Output: true (Date object type preserved)
Iteration
- Loops are also another control structure then if-else
- It’s like doing reps of an exercise
// for loop keeps running while the condition is true // This loop will run 11 times for(let rep = 0; rep <= 10; rep++){ console.log(`Lifting weights repetition ${rep} 🏋️`); }
Looping Arrays, Breaking & Continuing
- One very common use case of loops is to iterate over an array
- Keyword
continueis used to end current iteration andbreakis to terminate the entire loop
const teacher = [ "Jonas", "Schmedtmann", false, ["Michael", "Peter", "Steven"], 30, "Teacher", ] const newArr = []; // Only storing string values to newArr for(let i=0; i < teacher.length; i++){ // --- ONLY STRINGS --- // if(typeof teacher[i] !== 'string') continue; newArr.push(teacher[i]); } newArr; // ["Jonas", "Schmedtmann", "Teacher"]
Looping Backwards and Loops in Loops
- Here we are logging an array in reverse order
const pets = ["Zuzu", "Kittu", "Browzer"]; for(let i = pets.length - 1; i >= 0; i--){ console.log(pets[i]); }
- Doing 5 rep of each exercise
const exercises = ["Pushup", "Squat", "Leg Raises"]; for(let i = 0; i < exercises.length; i++){ for(let j=1; j <= 5; j++){ console.log(`Rep ${j} of ${exercises[i]} exercise.`); } } // Rep 1 of Pushup // Rep 2 of Pushup ... Rep 5 of Pushup // ... Rep 5 of Leg Raises
The while Loop
- Keeps looping while a condition is true, mostly used when we don’t prior know the number of iterations
- It is more versatile meaning that it can be used in more number of ways as it doesn’t require a counter
- It is the most common case for an infinite loop to occur
let rep = 1; // initalization while(rep <= 10); { // condition console.log(rep); rep++; // updater }
- This program uses a while loop to roll a die until a 6 is obtained
// Gives a value from 1 to 6 const rollDie = () => Math.floor(Math.random() * 6) + 1; // Attempts to roll until a 6 is Obtained function rollA6(){ let aRoll = rollDie(); console.log('--- first roll: ', aRoll); let totalAttempts = 1; while(aRoll !== 6){ aRoll = rollDie(); totalAttempts++; console.log('--- subsequent roll: ', aRoll); } console.log('--- final roll', aRoll); console.log(`It took ${totalAttempts} number of attempts!`); } rollA6();
for in and for of
for inloop is used to iterate over an object, giving the key on every iteration
for ofis used to iterate over an array
bas ab!