JavaScript (Cheat Sheet)
This is a cheat sheet on JavaScript (mostly notes-to-self). They are incomplete by default.
Basics
References (variables)
Source: Airbnb style guide .
Use const
for all of your references; avoid using var
.
Why? This ensures that you can’t reassign your references, which can lead to bugs and difficult to comprehend code.
// bad
var a = 1;
var b = 2;
// good
const a = 1;
const b = 2;
If you must reassign references, use let
instead of var
.
Why?
let
is block-scoped rather than function-scoped likevar
.
// bad
var count = 1;
if (true) {
count += 1;
}
// good, use the let.
let count = 1;
if (true) {
count += 1;
}
Both let
and const
are block-scoped, whereas var
is function-scoped.
// const and let only exist in the blocks they are defined in.
{
let a = 1;
const b = 1;
var c = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
console.log(c); // Prints 1
You can see that referencing a
and b
will produce a ReferenceError, while c
contains the
number. This is because a
and b
are block scoped, while c
is scoped to the containing
function.
Objects
-
JavaScript objects
- are key-value pairs that can contain strings, numbers, arrays, functions, booleans, and other objects
// JavaScript Object const jsObj = { name: "Alice", age: 30, };
-
JSON objects
-
are text-only (that means both keys and values are
strings
)// JSON Object const jsonObj = { name: "Alice", age: "30", };
-
you can validate JSON objects using jsonlint.com
-
Source: other notes .
Use the literal syntax for object creation.
// bad
const item = new Object();
// good
const item = {};
Use computed property names when creating objects with dynamic property names.
Why? They allow you to define all the properties of an object in one place.
function getKey(k) {
return `a key named ${k}`;
}
// bad
const obj = {
id: 5,
name: "San Francisco",
};
obj[getKey("enabled")] = true;
// good
const obj = {
id: 5,
name: "San Francisco",
[getKey("enabled")]: true,
};
Group your shorthand properties at the beginning of your object declaration.
Why? It’s easier to tell which properties are using the shorthand.
const anakinSkywalker = "Anakin Skywalker";
const lukeSkywalker = "Luke Skywalker";
// bad
const obj = {
episodeOne: 1,
twoJediWalkIntoACantina: 2,
lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker,
};
// good
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJediWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
Only quote properties that are invalid identifiers.
Why? In general we consider it subjectively easier to read. It improves syntax highlighting, and is also more easily optimized by many JS engines.
// bad
const bad = {
foo: 3,
bar: 4,
"data-blah": 5,
};
// good
const good = {
foo: 3,
bar: 4,
"data-blah": 5,
};
Source: Airbnb style guide .
Spread syntax (...
)
Source: developer.mozilla.org
The spread (...
) syntax allows an iterable, such as an array or string, to be expanded in
places where zero or more arguments (for function calls) or elements (for array literals) are
expected. In an object literal, the spread syntax enumerates the properties of an object and adds
the key-value pairs to the object being created.
Spread syntax looks exactly like rest syntax. In a way, spread syntax is the opposite of rest syntax. Spread syntax “expands” an array into its elements, while rest syntax collects multiple elements and “condenses” them into a single element. See rest parameters and rest property .
Spread syntax can be used when all elements from an object or array need to be included in a new array or object, or should be applied one-by-one in a function call’s arguments list. There are three distinct places that accept the spread syntax:
-
Function arguments
list (
myFunction(a, ...iterableObj, b)
) -
Array literals
(
[1, ...iterableObj, '4', 'five', 6]
) -
Object literals
(
{ ...obj, key: 'value' }
)
Although the syntax looks the same, they come with slightly different semantics.
Only
iterable
values, like
Array
and
String
can be spread in
array
literals
and argument lists. Many objects are not iterable, including all
plain
objects
that lack a
Symbol.iterator
method:
const obj = { key1: "value1" };
const array = [...obj]; // TypeError: obj is not iterable
Example:
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// Expected output: 6
Syntax:
myFunction(a, ...iterableObj, b)
[1, ...iterableObj, '4', 'five', 6]
{ ...obj, key: 'value' }
Rest parameters (...theArgs
)
Source: developer.mozilla.org
The rest parameter syntax allows a function to accept an indefinite number of arguments as an array, providing a way to represent variadic functions in JavaScript.
For example:
function sum(...theArgs) {
let total = 0;
for (const arg of theArgs) {
total += arg;
}
return total;
}
console.log(sum(1, 2, 3));
// Expected output: 6
Syntax:
function f(a, b, ...theArgs) {
// …
}
A function definition’s last parameter can be prefixed with ...
, which will cause all remaining
(user supplied) parameters to be placed within an
Array
object.
function myFun(a, b, ...manyMoreArgs) {
console.log("a", a);
console.log("b", b);
console.log("manyMoreArgs", manyMoreArgs);
}
myFun("one", "two", "three", "four", "five", "six");
// Console Output:
// a, one
// b, two
// manyMoreArgs, ["three", "four", "five", "six"]
A function definition can only have one rest parameter, and the rest parameter must be the last parameter in the function definition.
function wrong1(...one, ...wrong) {}
function wrong2(...wrong, arg2, arg3) {}
The rest parameter is not counted towards the function’s
length
property.
Rest property in destructuring assignments
Source: developer.mozilla.org
You can end a destructuring pattern with a rest property ...rest
. This pattern will store all
remaining properties of the object or array into a new object or array.
const { a, ...others } = { a: 1, b: 2, c: 3 };
console.log(others); // { b: 2, c: 3 }
const [first, ...others2] = [1, 2, 3];
console.log(others2); // [2, 3]
The rest property must be the last in the pattern, and must not have a trailing comma.
const [a, ...b] = [1, 2, 3];
// SyntaxError: rest element may not have a trailing comma
// Always consider using rest operator as the last element
Package managers (npm)
Source: devhints.io
Package management
Command | Description |
---|---|
npm i |
Alias for npm install |
npm install |
Install everything in package.json |
npm install --production |
Install everything in package.json, except devDependecies |
— | — |
npm install lodash |
Install a package |
npm install --save-dev lodash |
Install as devDependency |
npm install --save-exact lodash |
Install with exact |
— | — |
npm version 1.2.3 |
Bump the package version to 1.2.3 |
npm version major |
Bump the major package version by 1 (1.2.3 → 2.0.0) |
npm version minor |
Bump the minor package version by 1 (1.2.3 → 1.3.0) |
npm version patch |
Bump the patch package version by 1 (1.2.3 → 1.2.4) |
-D
flag is a shorthand for --save-dev
that saves the package as a dev-dependency.
--save
is the default as of npm@5. Previously, using npm install
without --save
doesn’t update
package.json.
Install names
Command | Description |
---|---|
npm i sax |
NPM package |
npm i sax@latest |
Specify tag latest |
npm i [email protected] |
Specify version 3.0.0 |
npm i sax@">=1 <2.0" |
Specify version range |
— | — |
npm i @org/sax |
Scoped NPM package |
— | — |
npm i user/repo |
GitHub |
npm i user/repo#master |
GitHub |
npm i github:user/repo |
GitHub |
npm i gitlab:user/repo |
GitLab |
— | — |
npm i /path/to/repo |
Absolute path |
npm i ./archive.tgz |
Tarball |
npm i https://site.com/archive.tgz |
Tarball via HTTP |
Listing
Command | Description |
---|---|
npm list |
Lists the installed versions of all dependencies in this software |
npm list -g --depth 0 |
Lists the installed versions of all globally installed packages |
npm view |
Lists the latest versions of all dependencies in this software |
npm outdated |
Lists only the dependencies in this software which are outdated |
Updating
Command | Description |
---|---|
npm update |
Update production packages |
npm update --dev |
Update dev packages |
npm update -g |
Update global packages |
— | — |
npm update lodash |
Update a package |
Removing
Command | Description |
---|---|
npm rm lodash |
Remove package production packages |
Misc features
# Add someone as an owner
npm owner add USERNAME PACKAGENAME
# list packages
npm ls
# Adds warning to those that install a package of old versions
npm deprecate PACKAGE@"< 0.2.0" "critical bug fixed in v0.2.0"
# update all packages, or selected packages
npm update [-g] PACKAGE
# Check for outdated packages
npm outdated [PACKAGE]
Runtime environment (Node.js)
How to start a simple Node project
- Create a repository on Github
- Clone the repo
- Add
.gitignore
(example below)
node_modules/
.env
.vscode
- Run
npm init
(takes you through mini questionnaire in CLI and creates file) - Run
npm install <your_required_package_name>
to install and add dependencies to thepackage.json
file
Package.json
To make package.json files from from scratch:
- run
npm init
(takes you through mini questionnaire in CLI and creates file) - run
npm install <package>
(automatically adds to dependency in the package.json file)
NVM (node version manager)
Node Version Manager is a tool that helps us manage Node versions and is a convenient way to install Node. Think of it as npm or Yarn that helps manage Node packages, but instead of packages, NVM manages Node versions.
Source: logrocket
Displaying a list of Node.js versions
We can now view all the versions we downloaded so far; currently, we have three Node versions installed using NVM.
To see the full list, run the following command:
nvm ls
The list then appears:
-> v12.22.5
v14.19.0
v18.3.0
system
default -> 12 (-> v12.22.5)
iojs -> N/A (default)
unstable -> N/A (default)
node -> stable (-> v18.3.0) (default)
stable -> 18.3 (-> v18.3.0) (default)
lts/* -> lts/gallium (-> N/A)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.17.1 (-> N/A)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.24.1 (-> N/A)
lts/erbium -> v12.22.12 (-> N/A)
lts/fermium -> v14.19.3 (-> N/A)
lts/gallium -> v16.15.1 (-> N/A)
Source: logrocket
Switching among Node.js Version
The best feature about NVM is the ability to easily switch between different Node versions.
nvm use 18.3.0
Source: logrocket
Removing a Node.js version
To remove a version, just run the following command:
nvm uninstall <the version number>
Source: logrocket
React.js
Resources:
- React docs > Learn React (beta) > Quick Start
- React docs > Hello world
React Elements
React elements are written just like regular HTML elements. You can write any valid HTML element in React:
<h1>My Header</h1>
<p>My paragraph>
<button>My button</button>
Source: freeCodeCamp - React cheat sheet for 2022
Styling: Inline styles are not written as plain strings, but as properties on objects:
<h1 style={{ fontSize: 24, margin: "0 auto", textAlign: "center" }}>My header</h1>
React Components
We can organize groups of elements into React components.
Here is the basic syntax of a React function component:
- Component names must start with a capital letter (that is, MyComponent, instead of myComponent)
- Components, unlike JavaScript functions, must return JSX.
function App() {
return <div>Hello world!</div>;
}
Source: freeCodeCamp - React cheat sheet for 2022
React Props
React components can accept data passed to them in objects called props
. Props are passed from
the parent component to a child component.
Here we are passing a prop name
from App to the User component.
function App() {
return <User name="John Doe" />;
}
function User(props) {
return <h1>Hello, {props.name}</h1>; // Hello, John Doe!
}
Or simpler (if only one attribute):
function App() {
return <User name="John Doe" />;
}
function User({ name }) {
return <h1>Hello, {name}!</h1>; // Hello, John Doe!
}
Source: freeCodeCamp - React cheat sheet for 2022
React conditionals
If statement:
function App() {
const isAuthUser = useAuth();
if (isAuthUser) {
// if our user is authenticated, let them use the app
return <AuthApp />;
}
// if user is not authenticated, show a different screen
return <UnAuthApp />;
}
Source: freeCodeCamp - React cheat sheet for 2022
Ternary list:
function App() {
const isAuthUser = useAuth();
return (
<>
<h1>My App</h1>
{isAuthUser ? <AuthApp /> : <UnAuthApp />}
</>
);
}
Source: freeCodeCamp - React cheat sheet for 2022
React Lists
Lists of React components can be output using the .map()
function.
.map()
allows us to loop over arrays of data and output JSX.
function SoccerPlayers() {
const players = ["Messi", "Ronaldo", "Laspada"];
return (
<div>
{players.map((playerName) => (
<SoccerPlayer key={playerName} name={playerName} />
))}
</div>
);
}
Source: freeCodeCamp - React cheat sheet for 2022
EthersJS
These are noob notes for the EthersJS web3 library (mostly notes-to-self). They are incomplete by default.
Provider (read-only)
Syntax:
new ethers.Contract(address, abi, signerOrProvider);
Source: EthersJS > Contract > Creating instances
Creates instance of Provider:
const { ethers } = require("ethers");
// Instantiate: Provider
const rpcUrl = "https://forno.celo.org";
const chainId = "42220";
const provider = new ethers.providers.JsonRpcProvider(rpcUrl, chainId);
Temporary bug: Some
issue
in ethers v6 with jsonRpcProvider
.
Signer (read and write)
const { ethers, Wallet } = require("ethers");
// Instantiate: Provider
const rpcUrl = "https://forno.celo.org";
const chainId = "42220";
const provider = new ethers.providers.JsonRpcProvider(rpcUrl, chainId);
// .env file
const dotenv = require("dotenv");
dotenv.config(); // to use .env file
// Instantiate: Signer
const privateKey = process.env.WALLET_PRIVATE_KEY;
const signer = new Wallet(privateKey, provider);
Contract
Contract functions
Syntax: You can add specific human-readable ABI (simply copy function signature from smart contract):
const abi = ["function getCurrentReleasedTotalAmount() public view returns (uint256)"];
E.g. this smart contract function:
/**
* @dev Calculates the total amount that has already released up to now.
* @return The already released amount up to the point of call.
* @dev The returned amount may vary over time due to locked gold rewards.
*/
function getCurrentReleasedTotalAmount() public view returns (uint256)
Example:
// Instantiate: Contract
const contractAddress = process.env.SMART_CONTRACT_ADDRESS;
const abi = ["function getCurrentReleasedTotalAmount() public view returns (uint256)"];
let contract = new ethers.Contract(contractAddress, abi, signer);
Contract variables
To query public variables via ethers, you can simply add getter function in your ABI with parentheses.
The compiler automatically creates getter functions for all public state variables. For the contract given below, the compiler will generate a function called
data
that does not take any arguments and returns auint
, the value of the state variabledata
.
Source: Solidity docs > Getter Functions , originally found via Stack Overflow
E.g.
const abi = ["function totalWithdrawn() public view returns (uint256)"];
// ...
const releaseSchedule = await releaseGoldContract.totalWithdrawn();
// ...
For the following public variable:
// Indicates how much of the released amount has been withdrawn so far.
uint256 public totalWithdrawn;
Source: Celo Monorepo > ReleaseGold.sol
Contract structs
Human-readable structs are not currently supported in ethers, but the following workaround makes them work:
While struct syntax is not supported, this works for me
const User = "(address user, string email)"; const abi = [ `event registered(${User} user)`, `function getId(${User} user) view returns (uint id)`, `function getUser(uint id) view returns (${User} user)`, `function addUser(${User} user)`, ]; const Relationship = `(${User} a, ${User} b, string relationship)`;
Source: Github > ethers-io > Issues
Example:
// Define struct-like variable
const ReleaseSchedule =
"(uint256 releaseStartTime, uint256 releaseCliff, uint256 numReleasePeriods, uint256 releasePeriod, uint256 amountReleasedPerPeriod)";
// Reference struct-like variable in ABI
const abi = [`function releaseSchedule() public view returns (${ReleaseSchedule})`];
// Query struct
const releaseSchedule = await releaseGoldContract.releaseSchedule();
console.log(releaseSchedule.toString());
For the
struct ReleaseSchedule {
// Timestamp (in UNIX time) that releasing begins.
uint256 releaseStartTime;
// Timestamp (in UNIX time) of the releasing cliff.
uint256 releaseCliff;
// Number of release periods.
uint256 numReleasePeriods;
// Duration (in seconds) of one period.
uint256 releasePeriod;
// Amount that is to be released per period.
uint256 amountReleasedPerPeriod;
}
// Public struct housing params pertaining to releasing gold.
ReleaseSchedule public releaseSchedule;
Source: Celo Monorepo > ReleaseGold.sol
Read-only methods
Querying a contract:
const { ethers } = require("ethers");
// Instantiate: Provider
const rpcUrl = "https://forno.celo.org";
const chainId = "42220";
const provider = new ethers.providers.JsonRpcProvider(rpcUrl, chainId);
// Instantiate: Contract
const contractAddress = process.env.SMART_CONTRACT_ADDRESS;
const abi = ["function getCurrentReleasedTotalAmount() public view returns (uint256)"];
let contract = new ethers.Contract(contractAddress, abi, signer);
// Query function in ReleaseGold.sol contract
const getReleasedAmountReceipt = await releaseGoldContract.getCurrentReleasedTotalAmount();
// Visualize response
console.log(ethers.utils.formatEther(getReleasedAmountReceipt.toString()));
Things to learn:
- State changing methods
- Listening to events
- Query historic events
- Signing Messages