-
Couldn't load subscription status.
- Fork 2
JavaScript
- Automatic semicolon insertion (ASI) will take effect in the presence of a newline.
- Any variable that you declare is by default defined in global scope.
- As a global variable is visible in all other scopes, a global variable can be modified by any scope.
- No block-level scope; instead, function-level scope.
var a = 1;
(function() {
var a = 2;
console.log( a ); // 2
})();
console.log( a ); // 1-
letkeyword to introduce traditional block scope (ES6).
var myv = 1;
let myl = "a";
const myc = true;
{
var myv = 2;
let myl = "b";
const myc = false;
console.log(myv + " " + myl + " " + myc);
myv = 3;
myl = "c";
// myc = true; /* cannot redefine a constant */
console.log(myv + " " + myl + " " + myc);
}
console.log(myv + " " + myl + " " + myc);prints:
2 b false
3 c false
3 a true
const key = 'name'
const user = {
[key]: 'Tomas',
}
console.log(user) // { name: 'Tomas' }Only var variables are partialy hoisted (only the variable name, not its value), functions are fully hoisted, let and const variables are not hoisted.
// prints Hello!
function a(){ console.log('Hi!') }
a();
function a(){ console.log('Hello!') }Wherever a var appears inside a scope, that declaration is taken to belong to the entire scope and accessible everywhere throughout.
a = 2
var a
console.log(a) // 2console.log(a) // undefined
var a = 2var a = 2;
foo(); // works because `foo()` function declaration is "hoisted"
function foo() {
a = 3;
console.log( a ); // 3
var a; // declaration is "hoisted" to the top of `foo()`
}
console.log( a ); // 2Function declarations are hoisted, but function expressions are not:
foo(); // TypeError
bar(); // ReferenceError
var foo = function bar() { ... }The variable identifier foo is hoisted and attached to the enclosing scope (global) of this program, so foo() doesn’t fail as a ReferenceError. But foo has no value yet (as it would if it had been a true function declaration instead of expression). So, foo() is attempting to invoke the undefined value, which is a TypeError illegal operation.
Hoisting happends on every execution context:
var a = 'A';
function f() {
console.log('1: a is', a); // 1: a is undefined
var a = 'AA';
console.log('2: a is', a); // 2: a is AA
}
f();Absence of meaningful values is indicated by two special values — null, when the non-value is deliberate, and undefined, when the value is not assigned to the variable yet.
var xl; // undefined
xl; // undefined
xl; // undefined
null == undefined; // true
An “undefined” variable is one that has been declared in the accessible scope, but at the moment has no other value in it. By contrast, an “undeclared” variable is one that has not been formally declared in the accessible scope.
With default parameters, undefined will use the default while null does not:
let logHi = (str = 'hi') => {
console.log(str);
}
logHi(undefined);
// hi
logHi(null);
// null- Prefer
undefinedtonull(nullis a bad idea).
// this is a safe existence check
if (typeof DEBUG !== "undefined") {
console.log( "Debugging is starting" );
}- Variables must be explicitly declared
- The with statement is not allowed.
- Octal literals are not allowed (eg.
010 === 8 true)
'use strict';
var decimal = 6;
var hex = 0xf00d;
var binary = 0b1010;
var octal = 0o744;
-
Number.MIN_VALUEandNumber.MAX_VALUE;Number.MAX_SAFE_INTEGERandNumber.MIN_SAFE_INTEGER -
Number.parseInt' andNumber.parseFloat' -
Number.NaNandNumber.isNaN
isNaN(NaN); // true
NaN == NaN; // false
isNaN("elephant"); // true
NaN + 5; // NaN
-
Math.E,Math.PI,Math.LOG10E,Math.LOG2E -
Math.abs,Math.pow,Math.sqrt,Math.min,Math.max,Math.trunc,Math.round,Math.ceil,Math.floor -
Math.random<0;1)
Math.random(); // 0.24329434322856125
Math.floor(Math.random() * Math.floor(5)); // 0,1,2,3,4In JavaScript, binary floating point numbers do not map correctly to Decimal numbers:
.1 + .2 // 0.30000000000000004- For true decimal math use
big.js
- Sequence of Unicode characters (each 16 bit)
- Quotes
'and double quotes"are equivalent. - Apostrophes (Grave accent) allows multiline-strings and variables resolution.
console.log(`Value: ${obj.value}`);- Strings are not just arrays of characters. Strings are immutable while arrays mutable.
"foo".repeat(3) // foofoofoo
"bar".startsWith("b") // true
"bar".endsWith("r") // true
"bar".includes("a") // trueThe following rules govern what becomes false (falsy values) and what turns out to be true (truthy values):
-
false,0(and"0"), the empty string (""),NaN,null, andundefinedare represented asfalse - everything else is
true
var oFalse = new Boolean(false);
var pFalse = false;
oFalse; // [Boolean: false]
pFalse; // false
oFalse == pFalse; // true
oFalse === pFalse; // false
if (pFalse) "It's true!" // undefined
if (oFalse) "It's true (but don't believe it)!" // It's true (but don't believe it)!
if (oFalse.valueOf()) "It false!" // undefined
typeof oFalse; // object
oFalse instanceof Boolean; // true
typeof pFalse; // boolean
pFalse instanceof Boolean; // falsevar a = new Boolean(false)
var b = new Number(0)
var c = new String("")
var d = Boolean( a && b && c ) // truea || b // roughly equivalent to: `a ? a : b`
a && b // roughly equivalent to: `a ? b : a`The && operator “selects” the second operand if and only if the first operand tests as truthy, and this usage is sometimes called the “guard operator” -- the first expression test “guards” the second expression:
foo = () => console.log( a )
var a = 42
a && foo() // 42-
==tries to do type coercion between two variables.
"" == "0" // false
0 == "" // true
"" === "0" // false
0 === "" // false- Always use
===and!==except for null checks
null == null // true
null == undefined // true
0 == null // false
'' == null // false
false == null // false
null === null // true
null === undefined // false
0 === null // false
'' === null // false
false === null // false[] == ![] // true -- before is even processed, it’s actually already translated to `[] == false`
0 == "\n" // true -- with empty "", "\n" (or " " or any other whitespace combination) is coerced to 0
42 == "43" // false
"foo" == 42 // false
"true" == true // false
42 == "42" // true
"foo" == ["foo"] // true- If either side of the comparison can have
trueorfalsevalues, never use== - If either side of the comparison can have
[],"", or0values, consider not using==
{a:123} == {a:123} // false
{a:123} === {a:123} // falseimport * as deepEqual from "deep-equal";
console.log(deepEqual({a:123},{a:123})); // trueThe spec says for a <= b, it will actually evaluate b < a first, and then negate that result. Since b < a is also false, the result of a <= b is true:
var a = { b: 42 }
var b = { b: 43 }
a < b // false
a == b // false
a > b // false
a <= b // true
a >= b // trueJavaScript store dates as the number of milliseconds since January 1, 1970, 00:00:00.
new Date() /* today */ // 2018-03-11T14:05:50.094Z
new Date(2000, 1, 25) // 2000-02-24T23:00:00.000Z
new Date(2000, 1, 25, 10, 20, 30, 444) // 2000-02-25T09:20:30.444Z
Date.now() // 1520777339877
Date.now() // 1520777340140
-
get/setFullYear,get/setMonth,get/setDate,get/setHours,get/setMinutes,get/setSeconds(and sets) get/setTime
There are many ways how to create a function:
-
named function declaration:
function first(...) {...}; -
anonymous function expression:
var second = function(...) {...}; -
named function expression:
var third = function someName(...) {...}; -
function constructor:
var fifth = new Function(...); -
arrow function:
var sixth = (...) => {...}; -
Immediately invoked function expression (IIFE)
// prints `hello!` immediately.
(function() {
console.log("hello!");
})();- The
thisparameter refers to an object that's implicitly associated with the function invocation, termed as a function context.
var santa = {
say: function() {
console.log("ho ho ho");
}
}
santa.say();function eventHandler(event){
event();
}
eventHandler(function(){
console.log("Event fired");
});function sum(a=0, b=0){
return (a + b);
}
console.log(sum(9,9)); // 18
console.log(sum(9)); // 9- Lexically captures the meaning of
this. - Lexically captures the meaning of
arguments.
console.log(( x => x * 3 )( 3 )); // 9
var f1 = () => console.log("Hello!");
f1(); // Hello!
var multiply = (a,b) => a * b;
console.log(multiply(2,2)); // 4
var multiply = (x,y) => {
if(x != 0 && y != 0) {
return x * y;
}
}
console.log(multiply(2,2)); // 4Inside an arrow function this is always the calling context.
let f = () => {
return { name: "Tomas" };
}
// could be written:
let f = () => ({ name: "Tomas" })
f() // { name: 'Tomas' }The spread operator expands an expression in places where you would otherwise require multiple arguments, elements, or variables.
function sum3(a, b, c) { return a + b + c; }
const x = [1, 2, 3];
const y = sum3(...x); // 6
const numbers = [2, 2, 9, 6, 0, 1, 2, 4, 5, 6];
const maxArray = arr => Math.max(...arr);
const maxA = maxArray(numbers); // 9A generator is a special kind of function that can start and stop one or more times, and doesn't necessarily ever have to finish.
function *foo() {
x++
yield // pause!
console.log( "x:", x )
}
function bar() {
x++
}
var x = 1
// construct an iterator `it` to control the generator
var it = foo()
// start `foo()` here!
it.next()
x // 2
bar()
x // 3
it.next() // x: 3function* dummyGenerator() {
yield 1;
yield 2;
yield 3;
}
var gen = dummyGenerator();
gen.next().value; // 1
gen.next().value; // 2
gen.next().value; // 3
gen.next().value; // undefinedfunction *foo(x) {
var y = x * (yield)
return y
}
var it = foo( 6 )
it.next()
var res = it.next( 7 )
res.value // 42The key concept is that when you define a function, it can refer to not only its own local variables, but also to everything outside of the context of the function:
function newCounter() {
let count = 0;
return function() {
return ++count;
};
}
const nc = newCounter();
console.log(nc()); // 1
console.log(nc()); // 2
console.log(nc()); // 3var v = 1
function a() {
function b() {
console.log(v)
}
return b
}
var f = a()
f() // 1
v = 2
f() // 2for (var i = 0; i < 10; i++) {
setTimeout(function() { console.log(i); }, 100 * i);
}
// 10 10 10 10 10 10 10 10 10 10for (let i = 0; i < 10 ; i++) {
setTimeout(function() { console.log(i); }, 100 * i);
}
// 0 1 2 3 4 5 6 7 8 9sum3 = x => y => z => x + y + z;
sum3(1)(2)(3); // 6const multiply = (a,b) => a*b
const multiplyByTwo = multiply.bind(this, 2)
multiplyByTwo(5) // 10Modules are used to mimic classes and focus on public and private access to variables and functions.
var moduleName = (function() {
// private state
// private functions
return {
// public state
// public variables
}
})()// module1.js
export function myfn1() { ... }
// module2.js
export default function myfn2() { ... }
// module3.js
export default function myfn3A() { ... }
export function myfn3B() { ... }<!-- index.html -->
<script type="module">
import { myfn1 } from './module1.js';
import myfn2 from './module2.js';
import myfn3A, { myfn3B } from './module3.js';
</script>JavaScript never shares data across threads, the function code is atomic - "run-to-completion" behaviour.
Asynchrony is implemented by a jobs queue.
console.log('A')
setTimeout(() => console.log('B'), 0)
console.log('C')
// A C B-
Synchronous callback is invoked before a function returns, that is, while the API receiving the callback remains on the stack. An example might be:
list.foreach(callback)whenforeach()returns, you would expect that the callback had been invoked on each element. -
Asynchronous or deferred callback is invoked after a function returns, or at least on another thread’s stack. Mechanisms for deferral include threads and main loops (other names include event loops, dispatchers, executors). Asynchronous callbacks are popular with IO-related APIs, such as
socket.connect(callback)you would expect that whenconnect()returns, the callback may not have been called, since it’s waiting for the connection to complete.
Callbacks should be either always sync or always async, as a documented part of the API contract - "Don't release Zalgo!"
In this example, the result (0 or 1) depends on conditions (sync or async callback invocation):
function callback(data) {
console.log(a)
}
var a = 0
ajax(url, callback)
a++const promisify = fn => (...args) => new Promise((resolve, reject) =>
fn(...args, (err, data) => (err ? reject(err) : resolve(data)))
);
promisify(/* do something expensive */)
.then(data => /* success 1 */)
.then(data => /* success 2 */)
.catch(err => /* error */) // catchs only error happened before
.then(data => /* success 3 */)
;function wait(ms) {
return new Promise(function (resolve, reject) {
setTimeout(resolve, ms)
})
}Promise.resolve('Success').then(function(value) {
console.log(value); // "Success"
});Promises are handled by the Job Queue in the JavaScript Runtime (browser, Node.js) which has higher priority than the Callback Queue (used for setTimeout) for the Event Loop:
setTimeout(()=>console.log(1), 0)
Promise.resolve(2).then(console.log)
console.log(3)
// 3 2 1 - The
asyncfunction declaration defines an asynchronous function, which returns anAsyncFunctionobject. - The
awaitoperator is used to wait for a Promise. It can only be used inside anasyncfunction.
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => { resolve(x); }, 2000);
});
}
async function f1() {
var x = await resolveAfter2Seconds(10);
console.log(x); // 10
}
f1();await is not a no-op. If the awaited thing is not a promise, it is wrapped in a promise, that promise is awaited. Therefore await changes the execution order:
// prints 1,2,3
console.log(1);
(async function() {
var x = await null; // remove await to see 1,3,2
console.log(3);
})();
console.log(2);this is the object that the function is a property of.
this represents the function’s context.
this is an implicit input.
When this is used, we need to always call the function with call() or apply() and pass in the context object.
While it may often seem that this is related to “object-oriented patterns,” in JS this is a different mechanism.
If a function has a this reference inside it, that this reference usually points to an object. But which object it points to depends on how the function was called.
-
thisdoes not refer to the function itself.
function say(thing) {
console.log(this + ' says ' + thing);
}
say.call("John", "hello"); // John says hello
say("hello"); // [object global] says hello - Node.js == say.call(global, "hello");
// [object Window] says hello - HTML browser == say.call(window, "hello");
var person = {
say: function(thing) {
console.log(this + ' says ' + thing);
}
say2: (thing) => {
console.log(this + ' says ' + thing);
}
};
person.say("hello"); // [object Object] says hello == person.say.call(person, "hello");
person.say2("hello"); // [object global] says hello - Node.js == person.say.call(global, "hello");
// [object Window] says hello - HTML browser == person.say.call(window, "hello");
class Person {
say(thing) {
console.log(this + ' says ' + thing);
}
}
var person = new Person();
person.say("hello"); // [object Object] says hello == person.say.call(person, "hello");When using arrow function, the lexical scope is preserved so this is referring to the context in which translated object has defined in, not the the actual object that holds the reference to the function.
var arr = new Array(1,2,3)
var arr = Array(1,2,3)
var arr = [1,2,3]var a = Array( 3 )
a.length // 3
a[0] // undefined
var b = Array.of( 3 )
b.length // 1
b[0] // 3
var c = Array.of( 1, 2, 3 )
c.length // 3
c // [1,2,3]// array-like object
var arrLike = { length: 3, 0: "foo", 1: "bar" }
var arr = Array.from( arrLike ) // [ 'foo', 'bar', undefined ]
var arrCopy = Array.from( arr ) // [ 'foo', 'bar', undefined ]var myArray = new Array("1", "2", "3");
var last = myArray.pop();
// myArray = ["1", "2"], last = "3"var myArray = new Array("1", "2");
myArray.push("3");
// myArray = ["1", "2", "3"]var a = [ ];
a[0] = 1;
// no `a[1]` slot set here
a[2] = [ 3 ];
a[1]; // undefined
a.length; // 3Arrays are numerically indexed, but they also are objects that can have string keys/properties added to them (but which don’t count toward the length of the array):
var a = [ ];
a[0] = 1;
a["foobar"] = 2;
a.length; // 1
a["foobar"]; // 2
a.foobar; // 2However, if a string value intended as a key can be coerced to a standard base-10 number, then it is assumed that you wanted to use it as a number index rather than as a string key:
var a = [ ];
a["13"] = 42;
a.length; // 14var colors = ['Red', 'Blue', 'Yellow'];
console.log(colors.length); // 3
colors.length = 2;
console.log(colors); // ["Red","Blue"] - Yellow has been removed
colors.length = 0;
console.log(colors); // [] the colors array is empty
colors.length = 3;
console.log(colors); // [undefined, undefined, undefined]colors.forEach(function(color) {
console.log(color);
});var myArray = new Array("33", "44", "55");
myArray = myArray.concat("3", "2", "1");
console.log(myArray);
// ["33", "44", "55", "3", "2", "1"]var myArray = new Array('Red','Blue','Yellow');
var list = myArray.join(", ");
console.log(list);
// "Red, Blue, Yellow"var myArray = new Array ("1", "2", "3");
myArray.reverse();
// transposes the array so that myArray = [ "3", "2", "1" ]var myArray = new Array("A", "C", "B");
myArray.sort();
// sorts the array so that myArray = [ "A","B","c" ]var a = ['a', 'b', 'a', 'b', 'a','c','a'];
console.log(a.indexOf('b')); // 1
// Now try again, starting from after the last match
console.log(a.indexOf('b', 2)); // 3
console.log(a.indexOf('1')); // -1, 'q' is not foundconst a1 = [1,1,3];
const a2 = [...new Set(a1)]; // [1,3][1, 2, 3].map(x => x * 10).reduce((sum,x) => sum + x) // 60
[1, 2, 3].map(function(x, idx, arr){ return arr[0] + x + idx + this.salt}, {salt: 100}) // 102, 104, 106
// reduceRight is starting at the end and looping until the beginning of the array
["a","b","c"].reduce((sum,x) => sum + x) // abc
["a","b","c"].reduceRight((sum,x) => sum + x) // cba
[1,2,3,4,5].filter(x => x > 2) // 3,4,5
[1,2,3,4,5].find(x => x > 2) // 3
[1,2,3,4,5].some(x => x > 2) // true
[1,2,3,4,5].every(x => x > 2) // false
// ES10
[1,2,[3,4,[5,6]]].flat() // [1, 2, 3, 4, Array(2)]
[1,2,[3,4,[5,6]]].flat().flat() // [1, 2, 3, 4, 5, 6]
// ES10
[1,2,3].flatMap(x => [x,x]) // [1, 1, 2, 2, 3, 3]// takes functions as parameters, each function takes x as a parameter
// await for the promise `y` and apply the next function (`f`)
// the result becomes the next `y`
const asyncPipe = (...fns) => x => (
fns.reduce(async (y, f) => f(await y), x)
)
const uploadFiles = asyncPipe(
readUser,
getFolderInfo,
haveWriteAccess,
uploadToFolder
)
uploadFiles({user, folder, files}) // a composited param `x` (merged params for all the functions)
.then(log)// Compose functions from top to bottom:
const pipe = (...fns) => x => fns.reduce((y, f) => f(y), x);
// Sugar to kick off the pipeline with an initial value:
const sumT = (...fns) => pipe(...fns)(t(0));
sumT(
t(2),
t(4),
t(-1)
).valueOf(); // 5Object.assign(destination, a, b)
/* or */
{...a, ...b}const delegate = (a, b) => Object.assign(Object.create(a), b);
const d = objs.reduceRight(delegate, {});var founders = new Map();
founders.set("facebook", "mark");
founders.set("google", "larry");
founders.size; // 2
founders.get("twitter"); // undefined
founders.has("yahoo"); // false
for (var [key, value] of founders) {
console.log(key + " founded by " + value);
}
// "facebook founded by mark"
// "google founded by larry"var mySet = new Set();
mySet.add(1);
mySet.add("Howdy");
mySet.add("foo");
mySet.has(1); // true
mySet.delete("foo");
mySet.size; // 2
for (let item of mySet) console.log(item);
// 1
// "Howdy"let input = [1, 2];
let [first, second] = input;
console.log(first); // outputs 1
console.log(second); // outputs 2
// swap variables
[first, second] = [second, first];var [x, y, ...remaining] = [1, 2, 3, 4];
console.log(x, y, remaining); // 1, 2, [3,4]
// destructuring with ignore
var [x, , ...remaining] = [1, 2, 3, 4];
console.log(x, remaining); // 1, [3,4]
// object destructuring
var {w, x, ...remaining} = {w: 1, x: 2, y: 3, z: 4};
console.log(w, x, remaining); // 1, 2, {y:3, z:4}
// destructuring for array items
var csvFileLine = '1997,John Doe,US,john@doe.com,New York';
var { 2: country, 4: state } = csvFileLine.split(',');
// destructuring for function parameters
var numbers = [1,2,3];
Math.max(...numbers); //3function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 }) {
// ...
}
// make the parameters optional
function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 } = {}) {
// ...
}var list = ['Apple','Orange','Banana'];
for (let i in list){
console.log(i); // 0 1 2
}
for (let i of list){
console.log(i); // Apple Orange Banana
}The in operator can be used to check if a property name exists in an object:
'b' in [a:1, b:2] // true
1 in [a:1, b:2] // false The in operator, when used together with arrays, will check if an index exists:
'b' in ['a', 'b'] // false
1 in ['a', 'b'] // true You can check for properties on built-in data types:
'length' in [] // true
'constructor' in Object // true
'a' in {a:1} // true switch (true) {
case (tempInCelsius <= 0):
state = 'Solid';
break;
case (tempInCelsius > 0 && tempInCelsius < 100):
state = 'Liquid';
break;
default:
state = 'Gas';
}var pattern = /test/flag;
var pattern = new RegExp("test", flag); /* alternatively */-
i: case-insensitive. -
g: matches all the instances of the pattern as opposed to the default of local, which matches the first occurrence only. -
m: allows matches across multiple lines.
> /orange/ig.test("Orange Juice") // true
/Toy/g.exec('A Toyota! Race fast, safe car! A Toyota!');
'A Toyota! Race fast, safe car! A Toyota!'.match(/Toy/g);
try {
var a = doesnotexist; // throws a runtime exception
} catch(e) {
console.log(e.message); // doesnotexist is not defined
} finally {
// will be always executed
}A return inside a finally has the special ability to override a previous return from the try or catch clause, but only if return is explicitly called:
function foo() {
try {
return 42
} finally {
// no `return ..` here, so no override
} }
function bar() {
try {
return 42
} finally {
// override previous `return 42`
return
} }
function baz() {
try {
return 42
} finally {
// override previous `return 42`
return "Hello"
} }
foo() // 42
bar() // undefined
baz() // Hellofunction willThrowException(){
throw new Error("Invalid State");
}try {
...
} catch {
console.log('Something went wrong.');
}let json = JSON.stringify({ name:"Tomas", surname:"Tulka"})
json // {"name":"Tomas","surname":"Tulka"}
let obj = JSON.parse(json)// a direct object
var author = {
firstname : "Douglas",
lastname : "Crockford",
book : {
title:"JavaScript- The Good Parts",
pages:"172"
}
};
Object.keys(author); // [ 'firstname', 'lastname', 'book' ]There is one default property for almost all objects, called a prototype.
function Person() {}
Person.prototype.cry = function() { console.log("Crying"); }
var bob = new Person()
bob.cry() // Cryingvar a = {v: "my value"}
var b = Object.create(a)
console.log(b.v) // my value
a.v = "updated"
console.log(b.v) // updatedvar anotherObject = { a: 2 }
var myObject = Object.create( anotherObject )
anotherObject.a // 2
myObject.a // 2
anotherObject.hasOwnProperty( "a" ) // true
myObject.hasOwnProperty( "a" ) // false
myObject.a++ // implicit shadowing!
anotherObject.a // 2
myObject.a // 3
myObject.hasOwnProperty( "a" ) // truevar Person = function(name) {
this.name = name;
};
var albert = new Person('Albert Einstein');
console.log(albert.name); // Albert EinsteinFunctions themselves are not constructors. However, when you put the new keyword in front of a normal function call, that
makes that function call a “constructor call.” In fact, new sort of hijacks any normal function and calls it in a fashion that constructs an object, in addition to whatever else it was going to do:
function NothingSpecial() {
console.log( "Don't mind me!" )
}
var a = new NothingSpecial()
// "Don't mind me!"
a // {}function Child() {}
Child.prototype = new Person();
var aChild = new Child();
console.log(aChild instanceof Child); //true
console.log(aChild instanceof Person); //true
console.log(aChild instanceof Object); //truevar person = {
firstname: "Albert",
lastname: "Einstein",
get fullname() {
return this.firstname +" "+this.lastname;
},
set fullname(_name){
var words = _name.toString().split(' ');
this.firstname = words[0];
this.lastname = words[1];
}
};
person.fullname = "Issac Newton";
console.log(person.firstname); // "Issac"
console.log(person.lastname); // "Newton"
console.log(person.fullname); // "Issac Newton"- Class declarations are not hoisted (you first need to declare your class and then access it) - in opposite of functions.
class Rectangle {
// Attributes have an implicit getter/setter.
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
// Static method
static calcDiagonal(h, w) {
return Math.sqrt(Math.pow(h,2) + Math.pow(w,2))
}
}
const square = new Rectangle(10, 10);
console.log(square.area); // 100
console.log(Rectangle.calcDiagonal(2,3)); // 3.605551275463989class Human {
speak() { console.log('Ecce homo!'); }
}
class Physicist extends Human {
speak() {
super.speak();
console.log('E=m*c^2'); }
}
var albert = new Physicist();
albert.speak(); // Ecce homo!\nE=m*c^2let obj = {
a: "foo",
b: 123,
c: {
d: "bar"
}
};
let { a, b, c: {d} } = obj;
a // 'foo'
b // 123
c // not defined
d // 'bar'
// Property renaming
let { a: newName1, b: newName2 } = obj;The first argument is the target, and any other arguments passed are the sources, which will be processed in listed order. For each source, its enumerable and own (e.g., not “inherited”) keys, not symbols, are copied as if by plain = assignment and the target object is returned:
var target = {}
var o1 = { a: 1 }, o2 = { b: 2 }
Object.assign( target, o1, o2 ) // { a: 1, b: 2 }
target // { a: 1, b: 2 }A proxy is a special kind of object you create that “wraps" — or sits in front of — another normal object.
Example: pre-define all the properties/methods for an object, and have an error thrown if a non-existent property name is subsequently used:
var obj = { a: 1, foo () { console.log("a:", this.a) } }
var handlers = {
get(target,key,context) {
if (Reflect.has( target, key )) {
return Reflect.get(target, key, context)
} else {
throw "No such property/method!";
}
} }
var pobj = new Proxy( obj, handlers )
pobj.a // 3
pobj.foo() // a: 3
pobj.b // Error: No such property/method!
pobj.bar() // Error: No such property/method!console.trace()-
console.time()&&console.timeEnd() console.memoryconsole.count('STUFF I COUNT')console.assert(false, 'Log me!')console.clear()console.table({name:"Tomas", age:33}, {name:"John", age:26},)
%s = string, %i = integer, %o = object, %f = float
console.log("Hello, %s. Your numer is %i.", "Tomas", 123)
// DON'T
function getRegisteredUsers (fields, include, fromDate, toDate) { /* implementation */ }
getRegisteredUsers(['firstName', 'lastName', 'email'], ['invitedUsers'], '2016-09-26', '2016-12-13')
// DO
function getRegisteredUsers ({ fields, include, fromDate, toDate }) { /* implementation */ }
getRegisteredUsers({
fields: ['firstName', 'lastName', 'email'],
include: ['invitedUsers'],
fromDate: '2016-09-26',
toDate: '2016-12-13'
})// AVOID
asyncFunc1((err, result1) => {
asyncFunc2(result1, (err, result2) => {
asyncFunc3(result2, (err, result3) => {
console.lor(result3)
})
})
})
// PREFER
asyncFuncPromise1()
.then(asyncFuncPromise2)
.then(asyncFuncPromise3)
.then((result) => console.log(result))
.catch((err) => console.error(err))- Jasmine: Behavior-driven testing (https://jasmine.github.io)
- Node.js: Server-side JavaScript runtime engine (https://nodejs.org)
- Express: Minimalist web framework for Node.js (https://expressjs.com)
- Underscore.js: Library for functional features and utilities (http://underscorejs.org)
- jQuery: Library for DOM traversal and manipulation (https://jquery.com)
- Backbone.js: MVC-framework for JavaScript applications (http://backbonejs.org)
- AngularJS: Framework for builing interactive single-page web applications (https://angularjs.org)
- React: Library for building user reactive interfaces (https://reactjs.org)
- Redux: State container for JavaScript apps (https://redux.js.org)
- CommonJS: Modularity framework (http://requirejs.org/docs/commonjs.html)
- Vue.js: Framework for building user interfaces (https://vuejs.org)
- Polymer: Library for building web applications using Web Components (https://www.polymer-project.org, https://www.webcomponents.org)
- Ved Antani: Mastering JavaScript
- Federico Kereki: Mastering JavaScript Functional Programming
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
- Alternatives to Classes in JS: https://youtu.be/1AJsAPszZJ0
- https://blog.risingstack.com/javascript-clean-coding-best-practices-node-js-at-scale
- https://medium.freecodecamp.org/9-neat-javascript-tricks-e2742f2735c3
- https://davidwalsh.name/javascript-objects
- http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony
- Kyle Simpson: You don't know JS (series)
- https://medium.com/javascript-scene/a-functional-programmers-introduction-to-javascript-composing-software-d670d14ede30
- https://medium.com/javascript-scene/composable-datatypes-with-functions-aec72db3b093
- https://medium.com/javascript-scene/the-hidden-treasures-of-object-composition-60cd89480381
- https://medium.com/javascript-scene/javascript-monads-made-simple-7856be57bfe8
- https://www.nearform.com/blog/wormholes-in-javascript/
- https://medium.com/coinmonks/everything-you-wanted-to-know-about-package-lock-json-b81911aa8ab8
- https://flaviocopes.com/javascript-regular-expressions
- https://codeburst.io/javascript-null-vs-undefined-20f955215a2
- https://medium.com/appsflyer/10-tips-for-javascript-debugging-like-a-pro-with-console-7140027eb5f6
- Cheatsheet for JavaScript array methods: https://gist.github.com/rauschma/f7b96b8b7274f2e2d8dab899803346c3
- Tips for JavaScript: https://medium.com/@bretcameron/12-javascript-tricks-you-wont-find-in-most-tutorials-a9c9331f169d
- JavaScript Quiz: http://davidshariff.com/js-quiz
- Clean Code in JavaScript: https://github.com/ryanmcdermott/clean-code-javascript
- Async Patterns: https://jdxcode.com/posts/2020-01-19-async-javascript-patterns-for-2020/
- AST Explorer: https://astexplorer.net/
- Equality Coercion Table: https://dorey.github.io/JavaScript-Equality-Table/
- JavaScript Visualized Serie
- Can (a== 1 && a ==2 && a==3) ever evaluate to true?
- Designing very large JavaScript applications
- A lot of JS questions
- Write your own arbitrary precision javascript math library
- Unicode in JavaScript
- Invisible JavaScript Backdoor
- Emoji under the hood
- New features by ES versions
- JavaScript WTF