A Quick intro to the greatest Programming Language ever created - PART 1
Top 60 essential JavaScript Concepts taken from the epic Fireship's JS Crash Course
A high-level single-threaded garbage-collected interpreted or JIT Compiled Prototype based multi-paradigm Dynamic language with a non-blocking event loop made in 1995 by Brendan Eich to add an easy-to-learn scripting language to the scripting browser got its name from “JAVA” famous during those times is a fully-featured language that continues to evolve through the ECMA Script Standards.
It is the only language other than Web Assembly that is supported by browsers
Atwood's law: Any app that can be built with JS will be eventually built with JS like:
Server-Side Applications with Node.js
Mobile Applications with React or Ionic
Desktop Apps with Electron
It’s an interpreted scripting language but tools like V8 & Chromium use a JIT Compiler to convert all code to machine code in parallel, then execute immediately at runtime
Although it’s a single-threaded language, it’s really good at handling IO-intensive jobs made possible by the non-blocking event loop that can queue up work in the background without blocking the main thread
Important JavaScript Concepts:
Its standard implementation is called the ECMAScript & is the default language of browsers but browsers are not the only Runtime for JS & Tools like NodeJS, Deno, and Cloudflare help to run JS on a server
It’s a Scripting language which means that means we can execute code on the fly through the console of the dev tools that come with the browser
It’s interpreted line by line as compared to other languages like C which are compiled ahead of time but that’s not an entirely correct reference as browsers use an engine called the V8 that makes JS runs very fast converting our into machine code with a process called JIT(Just In Time Compilation)
JS can be used directly in our program/on a webpage by using the Script Tag. The JS file can be added or an external file can be referenced using the “src” attribute
Variables can be defined using:
let: most common, can be reassigned later
var: 'avoid var unless you’re smart'
const: can’t be reassigned
The variable name used should be in CamelCase and can be given a value, if not given it automatically uses undefined as the data type
It’s a dynamically typed language which means that no data type annotations are necessary
It uses 7 primitive datatypes:
string
number
bigint
boolean
undefined
symbol
null
Note that null can be explicitly defined as a data type and can be re-defined later on in the program with a diff. data type like string
Any value that’s not primitive will inherit from the object class. eg., luckyNum = new Object();
Semicolons are optional in JS because the JS Parser will add them automatically if we left them out
The reason we have different types of variables in JS is the “lexical environment” which determines where variables work and where they don’t
The Global Scope when a variable is available for use from anywhere, usually present at the top
The Local Scope when a variable is available for use within a function
The Block Scope when is variable is defined within a block of statements like if-else
But, “var” is not block-scoped and is hoisted to be available in the function scope
When the function keyword is used to create a function in JS it’s referred to as the function definition/function statement and takes in arguments/params with a return value
Since Function is an object it can be used as a variable or even expression when the result of the function is stored in a variable which is known as a function expression. eg.,
function add(a, b) {
return a + b;
}
//Function Expression
const add = function(a, b){
return a + b;
}
- Due to the object nature of functions, it can be used for constructing higher-order functions where functions are used as the parameters or return type of a function. eg.,
function higherOrder(fun) {
fun();
return function () {
}
}
- Functions can be used as closure that encapsulates data & logic from the rest of the program. eg.,
function giveMeClosure(){
let a = 10;
function () {
a++;
return a;
}
}
Normally, when we call a function with a primitive value it gets stored on the “call stack” which is the browser’s short-term memory
But when we create a closure, the inner function has access to the variables defined in the outer function even after the initial function call because they’re automatically stored in the “Heap Memory” which will persist between function calls
This keyword - References to an object based on how a function is called:
- When used in the global scope, it references the global/window object. eg.,
function wtfIsThis() {
console.log(this);
}
- When attached to an object and used by that object, this refers to that very object
eg.,
const person = {
wtfIsThis: function(){
console.log(this);
}
}
- We can manually bind a function to another object using the “bind” method
eg.,
function wtfIsThis(){
console.log(this);
}
const person = {};
const personFun = wtfIsThis.bind(person)
- Modern JS uses arrow syntax to define functions. They don’t have their own list value and they’re always anonymous which makes them ideal for function expressions
const person = {
wtfIsThis: () => {
console.log(this);
}
}
When an argument with a primitive value is passed in a function, it’s “passed by value” ⇒ a copy of the original variable is created
But When an object is passed as an argument, it’s “passed by reference” ⇒ it’s stored in the heap and can be referred from any part of the program hence multiple parts of the code might be mutating the same object eg.,
const sum = 23;
const obj = new Object();
someFun(num, obj);
- Object Literal - Can be created in 2 ways:
- Using the object literal syntax with braces
eg., const human = { }
- Using the object constructor with the “new” keyword
eg., const human = new Object( );
- An object contains a collection of key-value pairs called properties eg.,
const human = {
dna: 'AACTG',
name: 'Jeff',
born: Date.now(),
walk() {
console.log('walking');
}
}
- Objects can inherit properties of another object through prototype chaining. Every object has a private property that links to a prototype which differs from class-based inheritance present in other languages because we’re dealing with real objects that take up memory as opposed to abstract classes in our code
//Do not use this in real life - eg of prototype chaining
human.__proto.__proto;
//Recommended way to get the prototype
Object.getPrototypeOf(human);
- JS supports OOP with the class keyword which is just syntactic sugar for prototypal inheritance and objects. A class can define a constructor which is a function that’s called when the object is first created. It can have multiple properties & optional getters and setters can be used to manipulate these properties. It can easily encapsulate functions by organizing them as methods on an object’s instance or making them global using the static method. eg.,
class Human {
constructor(name) {
this.dna = 'AACTG';
this.name = name;
}
get gender(){
return this.gender;
}
set gender(val) {
this.gender = val;
}
walk(){
console.log('walking');
}
static isHuman(human) {
if(human.dna == 'AACTG') {
return true;
}
}
- Data Structures:
Array: For holding a dynamic collection of indexed items
Set: For holding a collection of unique items
Map: For holding a collection of key-value pairs like object but can be easily looped over along with other features
const list = ['foo', 'bar', 'bar'] //Array
const uniq = new Set(list) //Set
//Map
const dict = new Map([
['foo', 1],
['bar', 2]
])
//WeakMAP
const weakDict = new WeakMap([
['foo', 1],
['bar', 2]
]);
- JS is Garbage Collected which means it’ll automatically de-allocate objects from memory if they’re no longer referencing our code but Map always references all the properties. If that’s not optimal, we can use WeakMap & WeakSet that can be garbage collected to optimize memory storage
Note: I really hope the reader found this helpful and enjoyed learning about JavaScript as much as I did. PART 2 will be published soon: )