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 like var.

// 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:

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

  1. Create a repository on Github
  2. Clone the repo
  3. Add .gitignore (example below)
node_modules/
.env
.vscode
  1. Run npm init (takes you through mini questionnaire in CLI and creates file)
  2. Run npm install <your_required_package_name> to install and add dependencies to the package.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 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:

  1. Component names must start with a capital letter (that is, MyComponent, instead of myComponent)
  2. 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 a uint, the value of the state variable data.

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