For non-JavaScript developers
In 1995 Netscape tasked Brendan Eich to create a new dynamic language for
the Web.
10 days later LiveScript is born.
As a collaboration with Sun Microsystems, LiveScript is renamed JavaScript as a complement to Java for web development.
Microsoft reverse engineers JavaScript, creates JScript for Internet Explorer 4.
In 1997 as Netscape quickly loses market shares, Brendan submits "JavaScript" to ECMA. Without copyright ownership of the name, JavaScript gets renamed as ECMAScript.
ECMAScript sees its first golden age as Ajax, a set of technologies for JavaScript and XML, gets released. JQuery, MooTools and many other libraries are released during this period.
In 2008 Google releases Chrome, using a new engine named V8, adds JiT and forces the work on ECMAScript to resume after Microsoft blockade, ES5 finally sees the light of day.
Enters JSConf 2009.
Announces Node.
Leaves.
In 2013 Facebook revolutionizes the web dev world by creating an endless amount of new jobs to fix React applications.
Compiler (TypeScript lives here!)
Scope
Engine
Compiler (TypeScript lives here!)
Generates & hoist code
Scope
Engine
Compiler (TypeScript lives here!)
Generates & hoist code
Scope
Maintains look-up lists
Engine
Compiler (TypeScript lives here!)
Generates & hoist code
Scope
Maintains look-up lists
Engine
Executes code
var a = 1;
function myFunc(b) {
console.log(a + b)
}
myFunc(2)
How many declarations are in this snippet?
var a = 1;
function myFunc(b) {
console.log(a + b)
}
myFunc(2)
a is declared in the global scope.
var a = 1;
function myFunc(b) {
console.log(a + b)
}
myFunc(2)
myFunc is declared in the global scope.
var a = 1;
function myFunc(b) {
console.log(a + b)
}
myFunc(2)
b is declared in myFunc scope.
var a = 1;
function myFunc(b) {
console.log(a + b)
}
myFunc(2)
LHS lookups: a,
b (implicit)
var a = 1;
function myFunc(b) {
console.log(a + b)
}
myFunc(2)
RHS lookups: a,
myFunc(2), a +,
+ b
var a = 1;
function myFunc(b) {
function myOtherFunc(c) {
console.log(a, b, c)
}
myOtherFunc(3)
}
myFunc(2) // 1, 2, 3
How many variables does each scope have?
var a = 1;
function myFunc(b) {
function myOtherFunc(c) {
console.log(a, b, c)
}
myOtherFunc(3)
}
myFunc(2) // 1, 2, 3
3 scopes, each has one variable
var a = 1; // shadowed by the other a
function myFunc() {
var a = 2
console.log(a)
}
myFunc() // 2
for (var i = 0; i < 10; i++) { // false scope
console.log(i)
}
if (true) {
var b = 20; // false scope
function f() { console.log(1) } // false scope
}
console.log(i, b) // 10, 20
f(); // 1
for (let i = 0; i < 10; i++) {
console.log(i)
}
if (true) {
const b = 20;
const f = () => { console.log(1) }
}
console.log(i, b) // Reference Error
f(); // Reference Error
setTimeout(() => { // bad
console.log(1)
}, 1000)
const a = () => { console.log(1) }
setTimeout(a, 1000) // good
function greetings() {
console.log("Hello I am", this.name);
}
var me = {
name: "Francesco"
}
var bossman = {
name: "Vlad"
}
greetings.call(me) // Hello I am Francesco
greetings.call(bossman) // Hello I am Vlad
let a = 1;
let b = a;
b = 2;
console.log(a) // 1
console.log(b) // 2
let realString = "a"
typeof realString // "string"
realString instanceof String // false
let objectString = new String("b")
typeof objectString // "object"
objectString instanceof String // true
Never use object constructors to define a primitive.
let a; // undefined
const b = () => {
return; // undefined
}
let c = [1,2].find(n => n === 3) // undefined
let obj = { a: 1, b: null };
typeof a.b === "undefined" // false
typeof a.c === "undefined" // true
!a.b // true
!a.c // true
let a = [1,2];
let b = a;
b.push(3);
console.log(a) // [1,2,3]
console.log(b) // [1,2,3]
class Animal {
void bark() {
System.out.println("ham ham");
}
}
class Dog extends Animal {
void eat() {
System.out.println("gnam gnam");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Own method
dog.bark(); // Inherited method
}
}
const animal = {
bark: () => console.log('ham ham')
};
const dog = Object.create(animal);
dog.eat = () => console.log('gnam gnam');
dog.eat(); // Own method
dog.bark(); // Inherited method
animal.bark = () => console.log('bau bau')
dog.bark(); // bau bau
class Animal {
bark() { console.log('ham ham'); }
};
class Dog extends Animal {
eat() { console.log('gnam gnam'); }
};
const myDog = new Dog();
myDog.eat(); // Own method
myDog.bark(); // Inherited method
Animal.prototype.bark = () => console.log('bau bau');
myDog.bark(); // bau bau
This works because 'class' is just syntactic sugar for the prototype
system.
fetchItalianJoke((joke) => {
// if (...)
translateJokeToRomanian(joke, (translateJoke) => {
// if (...)
doubleCheckTranslation(translateJoke, (correctTranslatedJoke) => {
// if (...)
postJoke(correctTranslatedJoke, () => {
// if (...)
console.log("Done!")
})
})
})
})
I have omitted reject/error for readibility purposes.
const getJoke = async () => {
try {
const joke = await fetchItalianJoke()
const translatedJoke = await translateJokeToRomanian(joke)
const correctTranslatedJoke = await doubleCheckTranslation(translatedJoke)
await postJoke(correctTranslatedJoke)
console.log("Done!")
} catch (err) { // err is block scoped!
console.error(err)
}
}
3 Block scopes, adding 10 more awaits will still max out at 3 block
scopes.
const num1 = 1;
const num2 = 2;
const sum = (a,b) => a + b;
const num3 = sum(num1, num2)
console.log(num1) // 1
console.log(num2) // 2
console.log(num3) // 3
for (let i = 0; i < 100; i++) {
// run this test 100 times
test('adding 2 numbers results in their sum', () => {
const r1 = Math.floor(Math.random() * 10) + 1 // 1-10
const r2 = Math.floor(Math.random() * 10) + 1 // 1-10
expect(sum(r1, r2)).toBe(r1 + r2);
});
}
const addNum = (arr) => { // impure
arr.push(arr.length + 1)
}
let numbers = [1,2,3,4]
addNum(numbers) // side effect on numbers
const addNum = (arr) => { // pure
return arr.length + 1
}
let numbers = [1,2,3,4]
let number = addNum(numbers) // no side effects
const a = 1
a = 2 // TypeError!
const b = { a: 1 }
b.a = 2 // { a: 2 }
const x = Object.freeze({ a: 1, b: { c: 2 }})
x.a = 2 // error
x.b.c = 1 // allowed
const updateUserRole = (user, role) => {
const newUser = { ...user, role }
return newUser
}
const reducer = (state, { type } = {}) => {
switch(type) {
case 'increment':
return { value: state.value + 1 }
default:
return state
}
}
const store = {
state: { value: 1 },
dispatch: function (action) {
this.state = reducer(this.state, action)
}
}
store.state // { value: 1 }
store.dispatch({ type: "increment" })
store.state // { value: 2 }
const stateSymbol = Symbol("state");
const store = {
[stateSymbol]: { value: 1 },
getState: function () {
return Object.freeze(this[stateSymbol])
},
dispatch: function (action) {
this[stateSymbol] = reducer(this[stateSymbol], action)
}
}
Check the MDN Docs.
Check the MDN Docs.
Complex animations or date manipulation are examples of complex problems.
Check the MDN Docs.
Complex animations or date manipulation are examples of complex problems.
Check GitHub and npm to assess the security risk and maintenence burden.