Aren't you? I'm always struggling to know where to use the for... of
loop or the for... in
loop.
Let's have here a quick note for reference:
Iterates over an iterable object (object, array, string, map...) and temporarily assign to a variable
const chars = ["Jack", "Daniel", "Sam", "Teal'c"];
for (const char of chars) {
console.log(char); }
Note that you can use const
if the variable is not reassigned within the loop.
Loops for properties of an array or object. Not to be used if the order is important.
// array
const chars = ["Jack", "Daniel", "Sam", "Teal'c"];
for (let char in chars) {
console.log(char); // prints the indexes as strings
console.log(chars[char]); // prints the value }
// object
const soldier = {firstname: "Jack", lastname: "O'Neill", team: "SG1"};
for (let key in soldier) {
console.log(key); // prints the key (firstname, lastname, team)
console.log(soldier[key]); // prints the value (Jack, O'Neill, SG1) }
The same result can be obtained using forEach() method (on an array).
const chars = ["Jack", "Daniel", "Sam", "Teal'c"];
chars.forEach(function (char, index) {
console.log(index); // prints the indexes as numbers
console.log(char); // prints the names
});
Learning React on FreeCodeCamp was confusing. For the first time in the curriculum I had to find some tutorials and go through W3C course as well to help me out. Let's hope writing down will help me understand how to use it.
A JavaScript library to build user interfaces thanks to its own markup language called JSX (combination of HTML and JavaScript). It was created and is maintained by Facebook.
React splits up the web page structure to separate components that can be displayed (rendered) according to a set of rules. To execute the rendition, the browser will need a transpiler (a converter) such as Babel.
React uses a virtual DOM where it does all the changes before passing them to the browser DOM.
Pen Settings/JS tab: select Babel as JavaScript Preprocessor
On JS tab add
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@18.2.0";
import * as React from "https://cdn.skypack.dev/react@18.2.0";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
)
And on HTML tab add
<div id="root"></div>
Make sure npx and Node.js are installed, then open a terminal and
ncd Documents/...
)npx create-react-app my-react-app
(my-react-app is the name of your app/directory)Wait a few minutes and it the React environment be ready. Then (and anytime later when located on your project directory), just run npm start
. A new browser window will pop up with your newly created React App! If not, open your browser and type localhost:3000
in the address bar. Changes you make will be visible immediately after you save the file, without reloading.
See all basics examples on CodePen. Each part is rendered in a different section for a better understanding but in this article we keep the rendering in a div with an id of root which is more common in real life.
React components are named functions that return HTML. If you have a project on your hardrive, you can split your work: 1 component equals 1 js file (Capitalized).
For instance:
in App.css
.red {color: red}
in Hello.js
function Hello() {
return <h2>Hello World!</h2>
}
export default Hello;
in App.js
import Hello from './Hello'
import './App.css';
function App() {
return <>
<h1 className="red">This is the App Name</h1>
<Hello/>
</>
}
Will be translated as:
<div id="root">
<h1 class="red">This is the App Name</h1>
<h2>Hello World!</h2>
</div>
Observations:
<>
and </>
fragment to enclose your code if there's no HTML tag to encapsulate it.Components can recieve properties (which would act as function arguments) from element's attributes. For instance:
function Yummy(prop) {
return <p>I love {prop.treat}!</p>
}
ReactDOM.render(
<React.StrictMode>
<Yummy treat="cookies" />
</React.StrictMode>,
document.getElementById("root")
)
prop
will regroup all attributes and children that where provided in an object, this is why we use the dot notation un Yummy fonction. If there's only a few attributes, we can just import in the function the needed key:
function Yummy( {treat, children} ) {
return <p>I love {treat}! {children ? <strong>{children}</strong> : "Reasonably."}</p>
}
ReactDOM.render(
<React.StrictMode>
<Yummy treat="chocolate">
<em>Too much, actually.</em>
</Yummy>
</React.StrictMode>,
document.getElementById("root")
)
Note that the code to be treated as JavaScript should be within curly braces. Methods (functions) can be passed as properties.
Let's have a look at this example for W3schools:
function Football() {
const shoot = (a) => {
alert(a);
}
return (
<button onClick={() => shoot("Goal!")}>Take the shot!</button>
);
}
ReactDOM.render(
<React.StrictMode>
<Football />
</React.StrictMode>,
document.getElementById("root")
)
Observations:
onClick
instead of onclick
)In this example, also from W3schools, we use two methods: && operator and ternary operator. We could also have used a classic if/else statement based on a prop value for instance (if prop is true, show this, else, show that).
function Garage(props) {
const cars = props.cars;
const message = `You have ${cars.length} cars in your garage.`;
return (
<>
<h3>Garage</h3>
{cars.length > 0 &&
<p>
Using && :<br/>
{message}
</p>
}
{
cars.length > 0 ?
<p>Using ternary operator :<br/>{message}</p> :
null
}
</>
);
}
const listofcars = [
{id: 1, brand: 'Ford'},
{id: 2, brand: 'BMW'},
{id: 3, brand: 'Audi'}
]
ReactDOM.render(
<React.StrictMode>
<Garage cars={listofcars} />
</React.StrictMode>,
document.getElementById("root")
)
Note: to use a variable within a string, nest the string intro backticks (`) and let you variable into curly brackets be preceded by a $ sign.
Use key for re-rendering only the element of a list that has been updated. Using the same listofcars
constant from above as well as the map JavaScript method (which iterates every item of provided list):
function Car(props) {
return <li>{ props.brand }</li>;
}
function Vroum() {
return (
<>
<h1>List of cars</h1>
<ul>
{listofcars.map((listofcars) => <Car key={listofcars.id} brand={listofcars.brand} />)}
</ul>
</>
);
}
ReactDOM.render(
<React.StrictMode>
<Vroum />
</React.StrictMode>,
document.getElementById("root")
)
Hooks connects rendering to particular changes which will be described here after. They replace class components since version 16.8. They can be customed, otherwise some are pre-made. All examples comes from W3Schools and are available on this CodePen.
First of all, if you have not imported all React features (using import * as React from
...), import the hooks you need, for instance:
import { useState, useEffect } from "react";
Doing so you are destructuring useState
from react
and can use it as is (rather than specify React.useState
like in CodePen).
And keep in mind these 3 rules from W3Schools:
- Hooks can only be called inside React function components.
- Hooks can only be called at the top level of a component.
- Hooks cannot be conditional
In this article we'll just focus on three main hooks but feel free to explore the other existing ones (useContext, useReducer, useCallback, useMemo).
Links a variable (its current state) to an updater function.
function App() {
const [color, setColor] = useState("yellow");
return <>
<p>My favorite color is {color}!</p>
<button
type="button"
onClick={() => setColor("blue")}
>Blue</button>
</>
}
Observations:
setVariablename
)useState("yellow")
initiates the variable to the value "yellow"
(a string)"blue"
as an argument (setting up a new state for color
)function App() {
const [car, setCar] = useState({
brand: "Ford",
model: "Mustang",
year: "1964",
color: "red"
});
const updateColor = () => {
setCar(previousState => {
return { ...previousState, color: "blue" }
});
}
return (
<>
<h1>My {car.brand}</h1>
<p>
It is a {car.color} {car.model} from {car.year}.
</p>
<button
type="button"
onClick={updateColor}
>Blue</button>
</>
)
}
Observations:
...previousState
) and indicate the change afterwards. Otherwise the entire object will be replaced with the only pair color: "blue"
.Perform side effect like fetching data, updating DOM, play with timers and runs on every render. Don't forget the second parameter (an empty array or an array containing dependencies) which will prevent auto re-rendering.
function Counter() {
const [count, setCount] = useState(0);
const [calculation, setCalculation] = useState(0);
useEffect(() => {
setCalculation(() => count * 2);
}, [count]); // if count updates, update calculation variable
return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount((c) => c + 1)}>+</button>
<p>Calculation: {calculation}</p>
</>
);
}
If there's a useEffect
hook on a timer, it should be disposed to reduce memory leaks; for this name the te timer and use a return statement to clear it:
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
let timer = setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
return () => clearTimeout(timer)
}, []);
return <h1>I've rendered {count} times!</h1>;
}
Can be used to access a DOM element directly or to keep track of previous state value. useRef()
returns an object called current
which should be intialized.
function Pointer() {
const inputElement = useRef();
const focusInput = () => {
inputElement.current.focus();
};
return (
<>
<input type="text" ref={inputElement} />
<button onClick={focusInput}>Focus Input</button>
</>
);
}
Using useRef, we associate the inputElement variable and the HTML element which have a ref attribute containing the variable's name. This is useful when we can't use getElementBySomething
because the real DOM is not already built.
function Before() {
const [inputValue, setInputValue] = useState("");
const previousInputValue = useRef("");
useEffect(() => {
previousInputValue.current = inputValue;
}, [inputValue]);
return (
<>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<h2>Current Value: {inputValue}</h2>
<h2>Previous Value: {previousInputValue.current}</h2>
</>
);
}
Both inputValue and previousInputValue are initialized to an empty string. Each time there's an event (e) in the input field:
inputValue
is updated via the setInputValue useState
function and the variable equals field's content
inputValue
is changed and as it's a depedancy, useEffect
comes in and replaces the value of current property to be equal to the inputValue
. It is not re-rendered until there's another event in the input field.We're done for now! Happy coding
Dividing the code into functions is essential.
Basically, a function can take an input (from zero to several parameters - a parameter can be a function) and provide a result whenever it's called.
In JavaScript, a function is a value.
A declared function is visible in the whole script.
function sayHello() {
console.log("hello")
}
The function name is usually a verb briefly describing the action. One function should do one action. Here's how to call it:
sayHello() // consols "hello"
When reached, the return keyword makes the function stop and returns the results if any (default return value is undefined)
function checkAge(age) { return age >= 18 ? true : false;}
checkAge(18) // returns true
checkAge(10) // returns false
A function can update variables without returning anything. For instance (from FreeCodeCamp) :
let sum = 0;
function addSum(num) {
sum = sum + num;
}
addSum(3); // sum variable now equals 3
console.log(addSum(3)) // returns undefined
Consider this function expecting three parameters:
function add(a, b, c) {
return a + b + c
}
If a parameter is not passed on, it's value is considered as undefined.
add(4, 2) // returns NaN (Not a Number)
You can specify a default value if the parameter is omitted:
function addition(a, b, c = 0) {
return a + b + c
}
add(4, 2) // returns 6
The rest parameter (...param) is useful if we want a function to work with a variable number of arguments. Arguments passed this way are stored as an array. Check out this example:
function howMany(...args) {
return args.length;
}
console.log(howMany(0, 1, 2)); // returns 3
console.log(howMany("string", null, [1, 2, 3], { })); // returns 4
If parameter order does not matter, you can use a JSON object as a parameter:
function myFunction(params) {
// do something
}
myFunction( { prop1: value1, prop2: value2 } );
Anonymous or expressed functions are useful when we don't need to re-use them anywhere else in the code. It exists once it's reached. Here are two use-cases with possible syntax:
Examples from FreeCodeCamp:
const myFunc = function() {
const myVar = "value";
return myVar;
}
With ES6 it can be shortened into an arrow function:
const myFunc = () => {
const myVar = "value";
return myVar;
}
Note that if we only want a value to be returned, then "return" keyword as well as brackets surrounding the code can be omitted.
const myFunc = () => "value";
If we need to pass arguments, the same principle as for named functions applies, except than parenthesis enclosing the parameter can be omitted if there's only one parameter:
const doubler = item => item * 2;
doubler(4);
const multiplier = (item, multi) => item * multi;
multiplier(4, 2);
Consider this object literal declaration (from FreeCodeCamp) which returns an object containing two properties:
const getMousePosition = (x, y) => ({
x: x,
y: y
});
Since ES6 a syntactic sugar exists. It eliminates the redundancy:
const getMousePosition = (x, y) => ({ x, y });
Here, x will be converted to x: x.
Write the function into parenthesis and call it at the end with parenthesis as well. This is call a IIFE notation.
(function(a) {
console.log(a);
})("hey");
These past few weeks I learned about regular expressions. Here's a recap! Almost all examples come from FreeCodeCamp.
let stringToTest = "a string";
let regEx = /pattern/;
regEx.test(stringToTest); // returns false
returns true or false depending if the pattern is found or not
let ourStr = "Regular expressions";
let ourRegex = /expressions/;
ourStr.match(ourRegex); // returns ["expressions"]
returns an extraction of the string that matches the provided pattern.
let wrongText = "The sky is silver.";
let silverRegex = /silver/;
wrongText.replace(silverRegex, "blue"); // returns "The sky is blue"
searches for the described pattern and replacing it by a value of your choice.
You can also access capture groups in the replacement string with dollar signs ($) (see group capture in Patterns/Group elements/Reuse group).
"Code Camp".replace(/(\w+)\s(\w+)/, '$2 $1'); // returns "Camp Code"
This is actually not a method but a special pattern to look ahead in the string for patterns further along. It won't match the element.
Use (?=...) to verify the element ("...") is there
Use (?!=...) to verify the element ("...") is not there
let quit = "qu";
let noquit = "qt";
let quRegex= /q(?=u)/;
let qRegex = /q(?!u)/;
quit.match(quRegex); // returns ["q"] ("u" is there)
noquit.match(qRegex); // returns ["q"] ("u" is not there)
This is not a method either but note that regular expressions are by default greedy meaning they will find the longest possible part of a string that fits the regex pattern and returns it as a match.
let string = "titanic";
let regEx = /t[a-z]*i/;
string.match(regEx); // returns "titani"
You can use ? to change it to lazy matching meaning the regular expression will find the shortest possible part of the string.
let string = "titanic";
let regEx = /t[a-z]*?i/;
string.match(regEx); // returns "ti"
Append flag right after the end of a pattern (//) if you need to extend the search to the whole string and/or ignore letter case.
Use g flag to search or extract a pattern more than once.
let testStr = "Repeat, Repeat, Repeat";
let repeatRegex = /Repeat/g;
testStr.match(ourRegex); // returns ["Repeat", "Repeat", "Repeat"]
Use i flag to ignore letter case (ie the difference between uppercase and lowercase letters).
let repeatRegex = /ignorecase/i;
This regex can match the strings ignorecase, igNoreCase, and IgnoreCase.
Just concatenate them, for instance
let regEx = /search/gi
Define a character set between square brackets []
Inside, define a list of character or a range of characters, using a hyphen character - to seperate from and to elements. Letters and numbers can be combined.
let regEx1 = /aeiu/
let regEx2 = /[a-e]/
let regEx3 = /[3-9]/
let regEx4 = /[a-e3-9]/
let catStr = "cat";
let batStr = "bat";
let matStr = "mat";
let bgRegex = /[a-e]at/;
catStr.match(bgRegex); // returns ["cat"]
batStr.match(bgRegex); // returns ["bat"]
matStr.match(bgRegex); // returns null
Add ^ at the beginning of the character set you want to negate
let regEx = /[^aeiou]/gi // matches everything that is not a vowel
Use () to group elements
let testStr = "Pumpkin";
let testRegex = /P(engu|umpk)in/;
testRegex.test(testStr); // Returns true
A group is saved as a temporary "variable" that can be accessed within the same regex using a backlash and the number of the captured group (e.g. \1). The number corresponds to the position of their opening parentheses, starting at 1.
let repeatStr = "row row row your boat";
let repeatRegex = /(\w+) \1 \1/;
repeatRegex.test(repeatStr); // Returns true
repeatStr.match(repeatRegex); // Returns ["row row row", "row"]
Use ? right after the element
let american = "color";
let british = "colour";
let rainbowRegex= /colou?r/;
rainbowRegex.test(american); // Returns true
rainbowRegex.test(british); // Returns true
Use | (OR operator) between each element
let regEx = /yes|no/
Use wildcard character . to match any one character
let humStr = "I'll hum a song";
let hugStr = "Bear hug";
let huRegex = /hu./;
huRegex.test(humStr); // returns true
huRegex.test(hugStr); // returns true
Type the string you're looking for between / and /
let testStr = "Hello, my name is Kevin.";
let testRegex = /Kevin/;
testRegex.test(testStr); // returns true
Use \w
let longHand = /[A-Za-z0-9_]+/;
let shortHand = /\w+/;
For everything but letters, numbers and underscore, use \W (short hand for [^A-Za-z0-9_])
Use \d
let longHand = /[0-9]/;
let shortHand = /\d/;
For all non-numbers, use \D (short hand for [^0-9])
Use \s to look for whitespace, carriage return (\r), tab (\t), form feed (\f), new line (\n) and vertical tab (\v)
let longHand = /[\r\t\f\n\v]/;
let shortHand = /\s/;
For non-whitespace, use \S (shorthand for [^ \r\t\f\n\v])
Use ^ outside of a character set and at the beginning of the regex
let firstString = "Ricky is first and can be found.";
let notFirst = "You can't find Ricky now.";
let firstRegex = /^Ricky/;
firstRegex.test(firstString); // returns true
firstRegex.test(notFirst); // returns false
Use $ at the end of the regex
let theEnding = "This is a never ending story";
let storyRegex = /story$/;
storyRegex.test(theEnding); // returns true
let noEnding = "Sometimes a story will have to end";
storyRegex.test(noEnding); // returns false
Use + right after the character than can be found one or more times
let string1 = "abc"
let string2 = "aabc"
let string3 = "abab"
let regEx = /a+/g
string1.match(regEx); // returns [ 'a' ]
string2.match(regEx); // returns [ 'aa' ]
string3.match(regEx); // returns [ 'a', 'a' ]
Use * right after the character that can be found zero or more times
let soccerWord = "gooooooooal!";
let gPhrase = "gut feeling";
let oPhrase = "over the moon";
let goRegex = /go*/;
soccerWord.match(goRegex); // returns ["goooooooo"]
gPhrase.match(goRegex); // returns ["g"]
oPhrase.match(goRegex); // returns null
Specify a certain number of patterns using curly bracket {}
let A4 = "haaaah";
let A3 = "haaah";
let A100 = "h" + "a".repeat(100) + "h";
let multipleHA = /ha{3}h/;
multipleHA.test(A4); // returns false
multipleHA.test(A3); // returns true
multipleHA.test(A100); // returns false
To only specify the lower number of patterns, keep the first number followed by a comma.
let A4 = "haaaah";
let A2 = "haah";
let A100 = "h" + "a".repeat(100) + "h";
let multipleA = /ha{3,}h/;
multipleA.test(A4); // returns true
multipleA.test(A2); // returns false
multipleA.test(A100); // returns true
Put two numbers between the curly brackets, separated by a comma - for the lower and upper number of patterns.
let A4 = "aaaah";
let A2 = "aah";
let multipleA = /a{3,5}h/;
multipleA.test(A4); // returns true
multipleA.test(A2); // returns false
Let's continue our exploration of data sets in JavaScript by having a look at the objects!
An object is also a collection of data but in a structured way as it's stored by pairs of property (or key) / value. For instance:
const BOOK = {
title: "The Lord of the Rings",
"volumes": 3,
"main characters": ["Frodo", "Aragorn"],
9: ["Fellows", "Nazgul"]
};
Notes:
To access the propertie's value, you can either use the dot or the bracket notation:
const TITLE = BOOK.title;
const VOLUMES = BOOK["volumes"];
const MAIN_CHARACTERS = BOOK["main characters"];
const NINE = BOOK[9]
You can use the dot notation if your property in a string of a single word. Otherwise, user the bracket notation with quotes for strings and without for numbers.
Tip: not sure a property exists? Use optionnal chaining (?.)! It helps prevent errors when accessing nested properties that might be null or undefined.
console.log(BOOK?.isbn);
Properties stored as value of a variable can also be access with the bracket notation. For instance:
const MAIN_CHARACTERS = "main characters";
let charactersList = BOOK[MAIN_CHARACTERS];
console.log(charactersList);
will print
[ 'Frodo', 'Aragorn' ]
on the console.
This can be very useful for iterating through an object's properties.
The same principle applies to access to sub propertie's values, just continue to filter via bracket or dot notation until you reach your destination. For instance (from FreeCodeCamp):
const ourStorage = {
"desk": {
"drawer": "stapler"
},
"cabinet": {
"top drawer": {
"folder1": "a file",
"folder2": "secrets"
},
"bottom drawer": "soda"
}
};
ourStorage.cabinet["top drawer"].folder2; // returns string "secrets"
ourStorage.desk.drawer; // returns string "stapler"
To check if the property of a given object exists or not, use the .hasOwnProperty(propname) method. It returns true or false if the property is found or not. For instance:
BOOK.hasOwnProperty("title");
BOOK.hasOwnProperty("author");
The first hasOwnProperty returns true, while the second returns false.
Note: always use quotes for string properties, otherwise an error is thrown.
Use Object.keys() method. It takes an object as the argument and returns an array of strings representing each property in the object. The order is first all non-negative integer keys in ascending order by value, then other string keys in ascending chronological order of property creation. For instance:
Object.keys(BOOK) // returns [ '9', 'title', 'volumes', 'main characters' ]
Same principle. Use Object.values() method.
Object.values
(BOOK) // returns [ [ 'Fellows', 'Nazgul' ], 'The Lord of the Rings', 3, [ 'Frodo', 'Aragorn' ] ]
Same principle. Use Object.entries() method.
Object.entries
(BOOK) //returns [ [ '9', [ 'Fellows', 'Nazgul' ] ], [ 'title', 'The Lord of the Rings' ], [ 'volumes', 3 ], [ 'main characters', [ 'Frodo', 'Aragorn' ] ] ]
Use a for...in statement. It looks like this:
for (let item in BOOK) {
console.log(item);
} // logs 9, title, volumes, main characters, each value in its own line
Here, "item" is a variable we define - it could be any name. Its value will change at each iteration.
The example comes from FreeCodeCamp.
Consider this object:
const user = { name: 'John Doe', age: 34 };
To extract both values and assign them to variables you could use:
const { name, age } = user;
Read it as: "create constants named "name" and "age" containing values from "name" and "age" properties in "user" object". This is a shorthand equivalent of
const name = user.name;
const age = user.age;
A console.log on name and age would return John Doe and 34, each on its own line
const declaration can by bypassed. To protect data from mutation, use Object.freeze() function. The argument would be the object you'd like to freeze. For instance (from FreeCodeCamp):
let obj = {
name:"FreeCodeCamp",
review:"Awesome"
};
Object.freeze(obj);
obj.review = "bad";
obj.newProp = "Test";
obj.review and obj.newProp assignments will result in errors and the object wouldn't change.
Proceed like any other variable; using dot or bracket notation. For instance:
BOOK["main characters"][1] = "Sam";
BOOK["main characters"][2] = "Bill";
console.log(BOOK["main characters"]);
will print
[ 'Frodo', 'Sam', 'Bill' ]
on the console.
Proceed just like you would for updating. For instance:
BOOK.format = "";
BOOK["number of copies"] = 100;
BOOK[5] = "Hello";
BOOK object will now look like this:
{
'5': 'Hello', '9': [ 'Fellows', 'Nazgul' ], title: 'The Lord of the Rings', volumes: 3, 'main characters': [ 'Frodo', 'Aragorn' ],
format: '', 'number of copies': 100
}
Order has not much importance from an object perspective because you're not using indexes to access data. But if this is important, consider using the spread operator (I'll probably write a blog entry later on this subject). Note that number properties order themselves at the beginning of the object.
User the delete keyword and then target your property according to it's format. For instance:
delete BOOK.format;
delete BOOK["number of copies"];
delete BOOK[5];
I learned a few things about JavaScript on OpenClassrooms (taking Apprenez à programmer avec JavaScript & Écrivez du JavaScript pour le web courses). I didn't know it then but I was actually looking for DOM manipulation for my Qwixx project. Anyway, I'm refreshing my newbie knowledge by taking FreeCodeCamp JavaScript Algorithms and Data Structures course and here is a recap about arrays.
An array can store multiple pieces of data in a single variable. Each entry is separated by a comma and nested into square brackets. Just like this:
const SANDWICH = ["peanut butter", 1, true, ["bakery", "home-made"]];
An array containing another array is also called a multi-dimensional array. An array can also contain objects.
"peanut butter" | 1 | true | ["bakery", "home-made"] |
0 | 1 | 2 | 3 |
Arrays use zero-based indexing, so the first element in an array has an index of 0. Use square bracket notation to get the data associated to the index. For instance:
console.log(SANDWICH[0]);
const EATEN = SANDWICH[1];
console.log(EATEN);
will print "peanut butter" string and 1 number.
Note that additional pair of brackets refers to the next level of entries inside.
const BOUGHT_IN = SANDWICH[3][0];
console.log(BOUGHT_IN);
will print "bakery".
Use indexOf() method. It returns -1 if the item is not found. For instance:
SANDWICH.indexOf('peanut butter'); // returns 0
SANDWICH.indexOf('butter'); // returns -1
Use spread operator (...). For instance (from FreeCodeCamp):
const arr = [6, 89, 3, 45];
const maximus = Math.max(...arr); // maximus has the value of 89
Use a for loop. It looks like this:
let array = [1, 2, 3]
for (let i = 0; i < array.length; i++) {
console.log(array[i])
} // logs 1, 2, 3, each on its own line
Even if an array is defined as a const its entries are mutable. From our example,
SANDWICH[0] = "houmus";
SANDWICH now has the value
["houmus", 1, true, ["bakery", "home-made"]];
Use push() method. It takes one or more parameters and "pushes" them onto the end of an array. For instance:
const arr = [1, 2, 3];
arr.push(4);
arr now has the value [1, 2, 3, 4]
Use unshift() method. For instance:
const arr = [1, 2, 3];
arr.unshift(0);
arr now has the value [0, 1, 2, 3]
Use splice() method.
First argument: the index at which to begin deleting elements
Second argument (optional): the number of elements to be deleted
Third argument (optional): items to insert starting at that same index, searated by a comma
For instance (example from FreeCodeCamp):
const numbers = [10, 11, 12, 12, 15];
const startIndex = 3;
const amountToDelete = 1;
numbers.splice(startIndex, amountToDelete, 13, 14);
console.log(numbers); // returns [ 10, 11, 12, 13, 14, 15 ]
User spread operator (...). For instance (example from FreeCodeCamp):
let arrayToAppend = ['sage', 'rosemary', 'parsley', 'thyme'];
let mainArray = ['basil', 'cilantro', ...arrayToAppend, 'coriander'];
mainArray now has the value ['basil', 'cilantro', 'sage', 'rosemary', 'parsley', 'thyme', 'coriander']
Use pop() method. For instance:
const arr = [1, 2, 3];
arr.pop();
arr now has the value [1, 2]
Use shift() method. For instance:
const arr = [1, 2, 3];
arr.shift();
arr now has the value [2, 3]
Note: removed data can be returned if assigned to a variable. For instance:
const arr = [1, 2, 3];
let removedNumber = arr.pop();
let one = arr.shift();
removedNumber has the number 3 as a value and one, 1
You can also use splice() method!
First argument: the index at which to begin deleting elements
Second argument (optional): the number of elements to be deleted
For instance (from FreeCodeCamp):
let array = ['today', 'was', 'not', 'so', 'great'];
array.splice(2, 2); // array now has the value ['today', 'was', 'great']
Here we remove 2 elements, beginning with the third element (at index 2). array would have the value
Note: removed data can be returned if assigned to a variable.
I realized it was not working like classic variables like these:
let a = "first variable"; // a contains "first variable" string
let b = a; // a and b contain "first variable" string
b = "second variable"; // a contains "first variable" and b "second variable" string
let array1 = [1, 2, 3]; // array1 contains [1, 2, 3] array
let array2 = array1; // array1 and array2 contain [1, 2, 3] array
array2.unshift(0); // array1 and array2 contain [0, 1, 2, 3] array
Here, array2 behaves just like another pointer to the same object. Modifying array2 will modify array1 and inversely. So how can we copy an array? Here are several methods:
For instance:
let originalArray = ['great', 'awesome', 'super', 'wonderful'];
let copiedArray = [...originalArray];
originalArray remains unchanged and copiedArray has the same elements as originalArray.
With slice() method, we can copy or extract a given number of elements to a new array, leaving the original array unchanged. It takes 2 parameters:
First argument: the index at which to begin extraction
Second argument (optional): the index at which to stop extraction (not included)
For instance (example from FreeCodeCamp):
let weatherConditions = ['rain', 'snow', 'sleet', 'hail', 'clear'];
let todaysWeather = weatherConditions.slice(1, 3); // todaysWeather is ['snow', 'sleet']