Context: These are noob notes on JavaScript/TypeScript (mostly notes-to-self). They are incomplete by default.
- JavaScript References by Mozilla
- TypeScript Documentation
- RealPython: Python vs JavaScript for Pythonistas
JavaScript for pythonistas:
Python | JavaScript | |
---|---|---|
Code Editor / IDE | PyCharm, VS Code | Atom, VS Code, WebStorm |
Code Formatter | black | Prettier |
Dependency Manager | Pipenv, poetry | bower (deprecated), npm, yarn |
Documentation Tool | Sphinx | JSDoc, sphinx-js |
Interpreter | bpython, ipython, python | node |
Library | requests, dateutil | axios, moment |
Linter | flake8, pyflakes, pylint | eslint, tslint |
Package Manager | pip, twine | bower (deprecated), npm, yarn |
Package Registry | PyPI | npm |
Package Runner | pipx | npx |
Runtime Manager | pyenv | nvm |
Scaffolding Tool | cookiecutter | cookiecutter, Yeoman |
Test Framework | doctest, nose, pytest | Jasmine, Jest, Mocha |
Web Framework | Django, Flask, Tornado | Angular, React, Vue.js |
Source: therealpython
Data types:
- undefined
- null
- boolean
- string
"a"
\"a\"
'"a"'
'a'
- symbol
- number
- object
var
: any data type over time (global scope)let
: value can change - mutable (local scope)const
: value cannot change - immutable
var a = 7;
console.log(a)
>>> 7
var arr = ["a", 1];
var nestedArr = [["a", 1], ["b", 2]]
Adds to end of array (arr.push(<elements>)
):
var arr = [1, 2, 3]
arr.push(4)
// arr = [1, 2, 3, 4]
arr.push([5, 6])
// arr = [1, 2, 3, 4, [5, 6]]
Adds to start of array (arr.unshift(<elements>)
):
var arr = [1, 2, 3]
arr.unshift(0)
// arr = [0, 1, 2, 3]
arr.unshift([-2, -1])
// arr = [[-2, -1], 0, 1, 2, 3]
Removes from end of array (arr.pop()
):
var arr = [1, 2, 3]
var lastElement = arr.pop()
// arr = [1, 2] and lastElement = 3
Removes from start of array (arr.shift()
):
var arr = [1, 2, 3]
var firstElement = arr.shift()
// arr = [2, 3] and firstElement = 1
function someReusableFunction(){
console.log("hello world");
}
someReusableFunction()
function anotherReusableFunction(){
console.log("foo bar");
anotherReusableFunction()
// hello world
// foo bar
Functions with arguments:
function someFunctionWithArgs(a, b){
console.log(a - b);
}
someFunctionWithArgs(10, 3);
// 7
Function with return:
function subtract(a, b){
return a - b;
}
var result = subtract(10, 3);
// result = 7
Variable Scope:
- a
var
declared outside function body has global scope - a
var
declared in a function is scoped to the function, but (!) if it is declarated without keywordvar
in a function body it has global scope
Equality (==
) vs strict equality (===
):
==
attempts to covert both variables to a common data type (also for inequality!=
)===
does not perform type conversion (also for strict inequality!==
)
console.log(7 == '7')
// true
console.log(7 === '7')
// false
console.log(7 !== '7')
// true
console.log(7 != '7')
// false
- (in JS) objects are like arrays but instead of using indices you are using properties (like a key-value store or dictionnary in Python)
- you can assigning object properties with dot notation
- you can access object properties with bracket notation (good when
key
is a string with space, e.g. "location country")
// 1. create object
var myFriend = {
"name": "Joe",
"location": "Venezuela",
"age": 25,
"friend": ["everyone!"]
};
// 2. access properties
var myFriendsName = myFriend.name;
// Joe
var myFriendsLocation = myFriend["location"];
// Venezuela
// 3. update properties
myFriend.age = 31;
/*
{
name: 'Joe',
location: 'Venezuela',
age: 31,
friend: [ 'everyone!' ]
}
*/
// 4. add new properties
myFriend["profession"] = "happy coder";
/*
{
name: 'Joe',
location: 'Venezuela',
age: 31,
friend: [ 'everyone!' ],
profession: 'happy coder'
}
*/
// 5. delete a property
delete myFriend.location
/*
{
name: 'Joe',
age: 31,
friend: [ 'everyone!' ],
profession: 'happy coder'
}
*/
// 6. testing for property
myFriend.hasOwnProperty('name');
// true
Simply multiply Unix timestamp by 1000 to convert it to a JavaScript time, because Unix timestamp measures time as a number of seconds, whereas in JavaScript time is fundamentally specified as the number of milliseconds (elapsed since January 1, 1970 at 00:00:00 UTC).
// Timestamp in seconds
var unixTimestamp = 1651822834;
/* Create a new JavaScript Date object based on Unix timestamp.
Multiplied it by 1000 to convert it into milliseconds */
var date = new Date(unixTimestamp * 1000);
// Generate date string
console.log(date.toLocaleDateString("en-US")); // Prints: 5/6/2022
console.log(date.toLocaleDateString("en-GB")); // Prints: 06/05/2022
console.log(date.toLocaleDateString("default")); // Prints: 5/6/2022
// Generate time string
console.log(date.toLocaleTimeString("en-US")); // Prints: 1:10:34 PM
console.log(date.toLocaleTimeString("it-IT")); // Prints: 13:10:34
console.log(date.toLocaleTimeString("default")); // Prints: 1:10:34 PM
Source: Tutorial Republic > How to Convert a Unix Timestamp to Time in JavaScript
Syntax:
toLocaleDateString()
toLocaleDateString(locales)
toLocaleDateString(locales, options) // prints: "Thursday, December 20, 2012, UTC"
locale
:
// US English uses month-day-year order
console.log(date.toLocaleDateString("en-US"));
// "12/20/2012"
// British English uses day-month-year order
console.log(date.toLocaleDateString("en-GB"));
// "20/12/2012"
// Korean uses year-month-day order
console.log(date.toLocaleDateString("ko-KR"));
// "2012. 12. 20."
options
:
const options = {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
};
Example:
const date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
// request a weekday along with a long date
const options = {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
};
console.log(date.toLocaleDateString("de-DE", options));
// "Donnerstag, 20. Dezember 2012"
// an application may want to use UTC and make that visible
options.timeZone = "UTC";
options.timeZoneName = "short";
console.log(date.toLocaleDateString("en-US", options));
// "Thursday, December 20, 2012, UTC"
Source: MDN Web Docs > Date.prototype.toLocaleDateString()
Source: dev.to - The Difference Between NPM and Yarn
To see list of commands:
NPM - npm
Yarn - yarn
Install dependencies from package.json:
NPM - npm install
Yarn - yarn
Install a package and add to package.json:
NPM - npm install package --save
Yarn - yarn add package
Install a devDependency:
NPM - npm install package --save-dev
Yarn - yarn add package --dev
Remove a dependency:
NPM - npm uninstall package --save
Yarn - yarn remove package
Upgrade a package to its latest version:
NPM - npm update --save
Yarn - yarn upgrade
Install a package globally:
NPM - npm install package -g
Yarn - yarn global add package
- 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
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)
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
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 lsThe 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
The best feature about NVM is the ability to easily switch between different Node versions.
nvm use 18.3.0
Source: logrocket
To remove a version, just run the following command:
nvm uninstall <the version number>
Source: logrocket
Source: Stackdiary > Require vs. Import in JavaScript
One of the main differences between require
and import
is that
require
can only be used to import modules, whereasimport
can be used to import both modules and individual exports from those modules.
In general, import
is preferred over require because it is a more modern and flexible syntax,
and it will eventually replace require
in the language.
For example, if you have a module named myModule
, you can use require
to import the
entire module like this:
const myModule = require('myModule');
To import a specific export from the module, you would need to use the .
notation like this:
const myFunction = require('myModule').myFunction;
Using import
, you can import the entire module and all of its exports like this:
import * as myModule from 'myModule';
Or you can import a specific export like this:
import {myFunction} from 'myModule';
We recommend learning a little bit of JavaScript without types first to understand JavaScript’s runtime behaviors. [...] TypeScript uses the same runtime as JavaScript, so any resources about how to accomplish specific runtime behavior (converting a string to a number, displaying an alert, writing a file to disk, etc.) will always apply equally well to TypeScript programs.
Source: TypeScript Docs
OOP in TypeScript
C# and Java are what we might call mandatory OOP languages. In these languages, the class is the basic unit of code organization, and also the basic container of all data and behavior at runtime.
In JavaScript, functions can live anywhere, and data can be passed around freely without being inside a pre-defined class or struct. Free” functions (those not associated with a class) working over data without an implied OOP hierarchy tends to be the preferred model for writing programs in JavaScript.
Rethinking Types
In C# or Java, any given value or object has one exact type - either null, a primitive, or a known class type. In C# or Java, it’s meaningful to think of a one-to-one correspondence between runtime types and their compile-time declarations.
In TypeScript, it’s better to think of a type as a set of values that share something in common. Because types are just sets, a particular value can belong to many sets at the same time. How do you describe a value that either belongs in the string set or the number set? It simply belongs to the union of those sets:
string | number
.In TypeScript, objects are not of a single exact type. For example, if we construct an object that satisfies an interface, we can use that object where that interface is expected even though there was no declarative relationship between the two. TypeScript’s type system is structural, not nominal: We can use
obj
as aPointlike
because it hasx
andy
properties that are both numbers. The relationships between types are determined by the properties they contain, not whether they were declared with some particular relationship.
// Example
interface Pointlike {
x: number;
y: number;
}
interface Named {
name: string;
}
function logPoint(point: Pointlike) {
console.log("x = " + point.x + ", y = " + point.y);
}
function logName(x: Named) {
console.log("Hello, " + x.name);
}
const obj = {
x: 0,
y: 0,
name: "Origin",
};
logPoint(obj);
logName(obj);
Surpises with TS: Empty types
We can see that { k: 10 } has all of the properties that Empty does, because Empty has no properties. Therefore, this is a valid call
class Empty {}
function fn(arg: Empty) {
// do something?
}
// No error, but this isn't an 'Empty' ?
fn({ k: 10 });
- Read about page on handbook (3min)
Resources:
- React docs > Learn React (beta) > Quick Start
- React docs > Hello world
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>
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 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
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
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
These are noob notes for the EthersJS web3 library (mostly notes-to-self). They are incomplete by default.
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
.
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);
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);
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
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
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()));
Github: 0xarthurxyz/vanilla-js-css-html
Source: Youtube - 3 Javascript Projects Every Beginner Should Build
display: flex
In the flex layout model, the children of a flex container can be laid out in any direction, and can "flex" their sizes, either growing to fill unused space or shrinking to avoid overflowing the parent. Both horizontal and vertical alignment of the children can be easily manipulated.
Source: MDN docs
- React-data-grid (very impressive)
- Rsuite-table (very impressive)
- react-table
- Material-ui-table
- React-bootstrap-table
- ka-table
- tanStack table
Source: copycat.dev - react table
Demo: https://adazzle.github.io/react-data-grid/#/common-features
Code examples:
- All features: https://github.com/adazzle/react-data-grid/blob/main/website/demos/AllFeatures.tsx
- Common features: https://github.com/adazzle/react-data-grid/blob/main/website/demos/CommonFeatures.tsx
Source: Stack Overflow
A dot in css is for what is called a class.
They can be called almost anything, for example in your CSS you would create a class and add style for it (in this case, I'm making the background black);
.my-first-class {
background-color: #000;
...
}
and to apply this class to an HTML element, you would do the following
<body class="my-first-class">
...
</body>
this would mean the body of the page would become black.
Now, you can create classes for CSS style or you can reference HTML elements directly, for example (CSS again);
body {
background-color: #000;
}
would directly reference the <body>
element on the page and do the same again.
The main difference between the two is that CSS classes are reusable. By comparison, referencing the HTML tag directly will affect all tags on the page (that are the same), for example (CSS again);
body {
background-color: #000;
}
.my-first-class {
background-color: #FFF;
}
and now for some HTML;
<body>
<p class="my-first-class">This is the first line</p>
<p class="my-first-class">This is the second line</p>
</body>