<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button>CLICK ME</button>
<script>
const channel = new BroadcastChannel('myChannel');
document.getElementsByTagName('button')[0].addEventListener('click', e => {
channel.postMessage('Hello from Tab 1' + new Date().getSeconds);
console.log('CHANNEL 1');
});
channel.onmessage = event => {
console.log('Message received in Tab 2:', event.data);
console.log('CHANNEL 2');
};
</script>
</body>
</html>
/*
https://blog.carlosrojas.dev/quick-reference-guide-to-design-patterns-in-js-1ebeb1e1c605
*/
/* Singleton */
class Animal {
constructor() {
if (typeof Animal.instance === 'object') {
return Animal.instance;
}
Animal.instance = this;
return this;
}
}
export default Animal;
/* Prototype */
class Fruit {
constructor(name, weight) {
this.name = name;
this.weight = weight;
}
clone() {
return new Fruit(this.name, this.weight);
}
}
export default Fruit;
const apple = new Fruit('Apple', 150);
const clonedApple = apple.clone();
console.log(apple); // Originální ovoce
console.log(clonedApple); // Klonované ovoce
/* Factory */
class MovieFactory {
create(genre) {
if (genre === 'Adventure') return new Movie(genre, 10000);
if (genre === 'Action') return new Movie(genre, 11000);
}
}
class Movie {
constructor(type, price) {
this.type = type;
this.price = price;
}
}
export default MovieFactory;
/* Abstract Factory */
function foodProducer(kind) {
if (kind === 'protein') return proteinPattern;
if (kind === 'fat') return fatPattern;
return carbohydratesPattern;
}
function proteinPattern() {
return new Protein();
}
function fatPattern() {
return new Fat();
}
function carbohydratesPattern() {
return new Carbohydrates();
}
class Protein {
info() {
return 'I am Protein.';
}
}
class Fat {
info() {
return 'I am Fat.';
}
}
class Carbohydrates {
info() {
return 'I am carbohydrates.';
}
}
export default foodProducer;
/* Adapter */
class Soldier {
constructor(level) {
this.level = level;
}
attack() {
return this.level * 1;
}
}
class SuperSoldier {
constructor(level) {
this.level = level;
}
attackWithShield() {
return this.level * 10;
}
}
class SoldierAdapter {
constructor(superSoldier) {
this.superSoldier = superSoldier;
}
attack() {
return this.superSoldier.attackWithShield();
}
}
export { Soldier, SuperSoldier, SoldierAdapter };
// Vytvoření instance SuperSoldier
const superSoldier = new SuperSoldier(5);
// Vytvoření instance SoldierAdapter, který přijímá SuperSoldier jako argument
const soldierAdapter = new SoldierAdapter(superSoldier);
// Volání metody attack() na SoldierAdapteru, která skutečně volá attackWithShield() u SuperSoldiera
const result = soldierAdapter.attack();
console.log(result); // Vypíše: 50 (5 * 10)
/* Bridge */
class Soldier {
constructor(weapon) {
this.weapon = weapon;
}
}
class SuperSoldier extends Soldier {
constructor(weapon) {
super(weapon);
}
attack() {
return 'SuperSoldier, Weapon: ' + this.weapon.get();
}
}
class IronMan extends Soldier {
constructor(weapon) {
super(weapon);
}
attack() {
return 'Ironman, Weapon: ' + this.ink.get();
}
}
class Weapon {
constructor(type) {
this.type = type;
}
get() {
return this.type;
}
}
class Shield extends Weapon {
constructor() {
super('shield');
}
}
class Rocket extends Weapon {
constructor() {
super('rocket');
}
}
export { SuperSoldier, IronMan, Shield, Rocket };
// Vytvoření instancí zbraní
const shield = new Shield();
const rocket = new Rocket();
// Vytvoření instancí vojáků s různými zbraněmi
const superSoldier = new SuperSoldier(shield);
const ironMan = new IronMan(rocket);
// Útoky vojáků
console.log(superSoldier.attack()); // Vypíše: SuperSoldier, Weapon: shield
console.log(ironMan.attack()); // Vypíše: Ironman, Weapon: rocket
/* Composite */
//Equipment
class Equipment {
getPrice() {
return this.price || 0;
}
getName() {
return this.name;
}
setName(name) {
this.name = name;
}
}
class Pattern extends Equipment {
constructor() {
super();
this.equipments = [];
}
add(equipment) {
this.equipments.push(equipment);
}
getPrice() {
return this.equipments
.map(equipment => {
return equipment.getPrice();
})
.reduce((a, b) => {
return a + b;
});
}
}
class Cabbinet extends Pattern {
constructor() {
super();
this.setName('cabbinet');
}
}
// --- leafs ---
class FloppyDisk extends Equipment {
constructor() {
super();
this.setName('Floppy Disk');
this.price = 70;
}
}
class HardDrive extends Equipment {
constructor() {
super();
this.setName('Hard Drive');
this.price = 250;
}
}
class Memory extends Equipment {
constructor() {
super();
this.setName('Memory');
this.price = 280;
}
}
export { Cabbinet, FloppyDisk, HardDrive, Memory };
// Vytvoření jednotlivých listových tříd (FloppyDisk, HardDrive, Memory)
const floppyDisk = new FloppyDisk();
const hardDrive = new HardDrive();
const memory = new Memory();
// Vytvoření skříně a přidání jednotlivých listových tříd do skříně
const cabbinet = new Cabbinet();
cabbinet.add(floppyDisk);
cabbinet.add(hardDrive);
cabbinet.add(memory);
// Získání celkové ceny skříně
const totalPrice = cabbinet.getPrice();
console.log(`Total Price: ${totalPrice}`); // Vypíše: Total Price: 600
/* Decorator */
class Notification {
constructor(kind) {
this.kind = kind || "Generic";
}
getInfo() {
return `I'm a ${this.kind} Notification`;
}
}
class FacebookNotification extends Notification {
constructor() {
super("Facebook");
}
setNotification(msg) {
this.message = msg;
}
getInfo() {
return `${super.getInfo()} with the message: ${this.message}`;
}
}
class SMSNotification extends Notification {
constructor() {
super("SMS");
}
getInfo() {
return super.getInfo();
}
}
export { FacebookNotification, SMSNotification };
// Vytvoření instance SMSNotification
const smsNotification = new SMSNotification();
// Dekorace SMSNotification pomocí FacebookNotificationDecorator
const decoratedNotification = new FacebookNotificationDecorator(smsNotification);
// Získání informací o dekorované notifikaci
console.log(decoratedNotification.getInfo());
// Vypíše: I'm a SMS Notification decorated with Facebook feature
/* Facade */
class Cart {
constructor() {
this.discount = new Discount();
this.shipping = new Shipping();
this.fees = new Fees();
}
calc(price) {
price = this.discount.calc(price);
price = this.fees.calc(price);
price += this.shipping.calc();
return price;
}
}
class Discount {
calc(value) {
return value * 0.85;
}
}
class Shipping {
calc() {
return 500;
}
}
class Fees {
calc(value) {
return value * 1.1;
}
}
export default Cart;
/* FlyWeight */
class Ingredient {
constructor(name) {
this.name = name;
}
getInfo() {
return `I'm a ${this.name}`
}
}
class Ingredients {
constructor() {
this.ingredients = {};
}
create(name) {
let ingredient = this.ingredients[name];
if (ingredient) return ingredient;
this.ingredients[name] = new Ingredient(name);
return this.ingredients[name];
}
}
export { Ingredients };
/* Proxy */
class Plane {
fly() {
return 'flying';
}
}
class PilotProxy {
constructor(pilot) {
this.pilot = pilot;
}
fly() {
return this.pilot.age < 18 ? `too young to fly` : new Plane().fly();
}
}
class Pilot {
constructor(age) {
this.age = age;
}
}
export { Plane, PilotProxy, Pilot };
/* Iterator */
class Iterator {
constructor(el) {
this.index = 0;
this.elements = el;
}
next() {
return this.elements[this.index++];
}
hasNext() {
return this.index < this.elements.length;
}
}
export default Iterator;
// Importujte váš Iterator
import Iterator from './Iterator';
// Vytvořte nějakou kolekci dat (v tomto případě pole).
const collection = ['Prvek 1', 'Prvek 2', 'Prvek 3'];
// Vytvořte instanci Iteratoru, předávejte kolekci jako argument konstruktoru.
const iterator = new Iterator(collection);
// Projděte kolekci pomocí Iteratoru.
while (iterator.hasNext()) {
const element = iterator.next();
console.log(element);
}
/* Mediator */
class TrafficTower {
constructor() {
this.airplanes = [];
}
getPositions() {
return this.airplanes.map(airplane => {
return airplane.position.showPosition();
});
}
}
class Airplane {
constructor(position, trafficTower) {
this.position = position;
this.trafficTower = trafficTower;
this.trafficTower.airplanes.push(this);
}
getPositions() {
return this.trafficTower.getPositions();
}
}
class Position {
constructor(x,y) {
this.x = x;
this.y = y;
}
showPosition() {
return `My Position is ${x} and ${y}`;
}
}
export { TrafficTower, Airplane, Position };
const trafficTower = new TrafficTower();
const airplane1 = new Airplane(new Position(10, 20), trafficTower);
const airplane2 = new Airplane(new Position(30, 40), trafficTower);
// Informovat TrafficTower o pozici letadla.
airplane1.getPositions();
// Získat informace o pozicích ostatních letadel pomocí TrafficTower.
airplane2.getPositions();
/* State */
class OrderStatus {
constructor(name, nextStatus) {
this.name = name;
this.nextStatus = nextStatus;
}
next() {
return new this.nextStatus();
}
}
class WaitingForPayment extends OrderStatus {
constructor() {
super('waitingForPayment', Shipping);
}
}
class Shipping extends OrderStatus {
constructor() {
super('shipping', Delivered);
}
}
class Delivered extends OrderStatus {
constructor() {
super('delivered', Delivered);
}
}
class Order {
constructor() {
this.state = new WaitingForPayment();
}
nextPattern() {
this.state = this.state.next();
}
}
export default Order;
// Vytvořte instanci objednávky
const order = new Order();
// Zjistěte aktuální stav
console.log(order.state.name); // Výstup: 'waitingForPayment'
// Přejděte na další stav
order.nextPattern();
// Zjistěte nový stav
console.log(order.state.name); // Výstup: 'shipping'
// Přejděte na další stav
order.nextPattern();
// Zjistěte nový stav
console.log(order.state.name); // Výstup: 'delivered'
/* Strategy */
class ShoppingCart {
constructor(discount) {
this.discount = discount;
this.amount = 0;
}
checkout() {
return this.discount(this.amount);
}
setAmount(amount) {
this.amount = amount;
}
}
function guest(amount) {
return amount;
}
function regular(amount) {
return amount * 0.9;
}
function premium(amount) {
return amount * 0.8;
}
export { ShoppingCart, guest, regular, premium };
// Importujte třídu ShoppingCart a slevové strategie
import { ShoppingCart, guest, regular, premium } from './ShoppingCart';
// Vytvořte instanci nákupního košíku s různými slevovými strategiemi
const cartGuest = new ShoppingCart(guest);
const cartRegular = new ShoppingCart(regular);
const cartPremium = new ShoppingCart(premium);
// Nastavte množství v košíku
cartGuest.setAmount(100);
cartRegular.setAmount(100);
cartPremium.setAmount(100);
// Proveďte platbu s různými slevovými strategiemi
console.log(cartGuest.checkout()); // Výstup: 100 (žádná sleva)
console.log(cartRegular.checkout()); // Výstup: 90 (10% sleva pro běžného zákazníka)
console.log(cartPremium.checkout()); // Výstup: 80 (20% sleva pro prémiového zákazníka)
/* Template */
class Tax {
calc(value) {
if (value >= 1000) value = this.overThousand(value);
return this.complementaryFee(value);
}
complementaryFee(value) {
return value + 10;
}
}
class VAT extends Tax {
constructor() {
super();
}
overThousand(value) {
return value * 1.1;
}
}
class GST extends Tax {
constructor() {
super();
}
overThousand(value) {
return value * 1.2;
}
}
export { VAT, GST };
// Importujte třídy VAT a GST
import { VAT, GST } from './Tax';
// Vytvořte instanci třídy VAT a provedte výpočet daně
const vatTax = new VAT();
console.log(vatTax.calc(1200)); // Výstup: 1320 (včetně přirážky pro hodnoty nad 1000)
// Vytvořte instanci třídy GST a provedte výpočet daně
const gstTax = new GST();
console.log(gstTax.calc(1200)); // Výstup: 1440 (včetně přirážky pro hodnoty nad 1000)
function counter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const increment = counter();
increment(); // Output: 1
increment(); // Output: 2
// OR
function createCounter() {
let count = 0;
return {
increment: function() {
count++;
},
decrement: function() {
count--;
},
getCount: function() {
return count;
}
};
}
const counter = createCounter();
counter.increment();
console.log(counter.getCount()); // Output: 1
// https://levelup.gitconnected.com/5-ways-to-create-an-object-in-javascript-55d556193ee8
// 1 . Object Literals
const car = {
make: 'Toyota',
model: 'Corolla',
year: 2021
};
console.log(car);
// 2. The new Object() Syntax
const person = new Object();
person.name = 'John';
person.age = 30;
person.isEmployed = true;
console.log(person);
// 3. Constructor Functions
function Smartphone(brand, model, year) {
this.brand = brand;
this.model = model;
this.year = year;
}
const myPhone = new Smartphone('Apple', 'iPhone 13', 2021);
console.log(myPhone);
// 4 The Object.create() Method
const animal = {
type: 'Animal',
displayType: function() {
console.log(this.type);
}
};
const dog = Object.create(animal);
dog.type = 'Dog';
dog.displayType(); // Output: Dog
// ES6 Class Syntax
class Book {
constructor(title, author, year) {
this.title = title;
this.author = author;
this.year = year;
}
getSummary() {
return `${this.title} was written by ${this.author} in ${this.year}`;
}
}
const myBook = new Book('1984', 'George Orwell', 1949);
console.log(myBook.getSummary());
class Item {
static count = 0
static count2 = 0
constructor(name) {
this.name = name
this.constructor.count++
Item.count2++
console.log(this)
console.log('-----------------------------------------')
console.log(this.constructor)
}
static getCount() {
return Item.count
}
static getCount2() {
return Item.count2
}
}
let A = new Item("A");
let B = new Item("B");
/*
console.log(A.getCount()) // nelze
console.log(B.getCount2()) // nelze
*/
console.log(Item.getCount()) // 2
console.log(Item.getCount2()) // 2
/*
[object Object] {
name: "A"
}
"-----------------------------------------"
class Item {
static count = 0
static count2 = 0
constructor(name) {
this.name = name
this.constructor.count++
Item.count2++
window.runnerWindow.proxyConsole.log(this)
window.runnerWindow.proxyConsole.log('-----------------------------------------')
window.runnerWindow.proxyConsole.log(this.constructor)
}
*/
let sayHiMixin = {
sayHi() {
alert(`Hello ${this.name}`);
}
}
let sayByeMixin = {
sayBye() {
alert(`Bye ${this.name}`);
}
}
class User {
constructor(name) {
this.name = name;
}
}
// copy the methods
Object.assign(User.prototype, sayHiMixin);
Object.assign(User.prototype, sayByeMixin);
const user = new User("Dude")
user.sayHi()
user.sayBye()
// after our data inside the Vue instance
computed: {
currentImage () {
return images[this.currentImageIndex]
},
previousImageIndex () {
return (this.currentImageIndex - 1 + images.length) % images.length
},
previousImage () {
return images[this.previousImageIndex]
},
nextImageIndex () {
return (this.currentImageIndex+1) % images.length
},
nextImage () {
return images[this.nextImageIndex]
},
}
// MUJ :D
Array.from(document.querySelector('.default').querySelectorAll('tr')).reduce((acc, tr) => {
let num = parseInt(tr.children[5].textContent)
if (!isNaN(num)) {
return acc + num
}
return acc
}, 0)
// GPT
const total = [...document.querySelectorAll('.default tr')]
.map(tr => parseInt(tr.children[5].textContent))
.filter(num => !isNaN(num))
.reduce((acc, num) => acc + num, 0);
// Variants
let total = 0;
document.querySelectorAll('.default tr').forEach(tr => {
let num = parseInt(tr.children[5].textContent);
if (!isNaN(num)) {
total += num;
}
});
const total = [...document.querySelectorAll('.default tr')].reduce((acc, tr) => {
const num = parseInt(tr.children[5].textContent);
return !isNaN(num) ? acc + num : acc;
}, 0);
const total = [...document.querySelectorAll('.default tr')].reduce((acc, tr) =>
acc + (parseInt(tr.children[5].textContent) || 0), 0);
const total = [...document.querySelectorAll('.default tr')].reduceRight((acc, tr) => {
const num = parseInt(tr.children[5].textContent);
return !isNaN(num) ? acc + num : acc;
}, 0);
/*
Resources:
- https://javascript.plainenglish.io/10-reduce-techniques-worth-mastering-97dd9b9a9e90
- https://andepaulj.medium.com/javascript-reduce-79aab078da23
- https://javascript.plainenglish.io/5-use-cases-for-reduce-in-javascript-61ed243b8fef
- https://code.tutsplus.com/5-real-life-uses-for-the-javascript-reduce-method--cms-39096a
*/
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const count = fruits.reduce((accumulator, currentValue) => {
accumulator[currentValue] = (accumulator[currentValue] || 0) + 1;
return accumulator;
}, {});
console.log(count); // Output: { apple: 3, banana: 2, orange: 1 }
/* Counting Occurrences */
const fruits = [ 'Banana', 'Orange', 'Apple', 'Orange', 'Pear', 'Banana']
const occurrences = fruits.reduce((acc, currFruit) => {
return {...acc, [currFruit]: (acc[currFruit] || 0) + 1 }
}, {})
console.log(occurrences)
/*
{
Apple: 1,
Banana: 2,
Orange: 2,
Pear: 1
}
*/
// OR
const reduceOccurrences = manyNumbers.reduce((acc, cur) => {
acc[cur] ? acc[cur]++ : acc[cur] = 1
return acc
}, {})
// OR via Map()
const count = (array) =>
array.reduce(
(acc, it) => (acc.set(it, (acc.get(it) || 0) + 1), acc),
new Map()
);
const array = [1, 2, 1, 2, -1, 0, "0", 10, "10"];
console.log(count(array));
/* Flatten a List of Arrays */
const arrOfArrs = [
['aaron', 'ake', 'anna', 'aje'],
['becky', 'ben', 'bright'],
['cara', 'chris'],
['david', 'daniel', 'danielle', 'djenue'],
]
const flattened = arrOfArrs.reduce((acc, array) => acc.concat(array))
console.log(flattened)
// ["aaron", "ake", "anna", "aje", "becky", "ben", "bright", "cara", "chris", "david", "daniel", // "danielle", "djenue"]
// OR
const array = [1, [2, [3, [4, [5]]]]];
const flat = (arrayNumbers) =>
arrayNumbers.reduce(
(acc, it) => acc.concat(Array.isArray(it) ? flat(it) : it),
[]
);
const flatArray = flat(array);
console.log(flatArray); // [ 1, 2, 3, 4, 5 ]
/* Getting Max and Min Values */
const students = [
{ name: "Kingsley", score: 70 },
{ name: "Jack", score: 80 },
{ name: "Joe", score: 63 },
{ name: "Beth", score: 75 },
{ name: "Kareem", score: 59 },
{ name: "Sarah", score: 93 }
]
const max = students.reduce((acc, student) => {
if(acc === null || student.score > acc)
return student.score
return acc
}, null)
console.log(max) // Prints 93
// OR
const getMax = (array) => array.reduce((max, num) => (max > num ? max : num));
const getMin = (array) => array.reduce((max, num) => (max < num ? max : num));
/* Converting Between Types */
const studentsArray = [
{ name: "Kingsley", score: 70, position: "1st" },
{ name: "Jack", score: 80, position: "2nd" },
{ name: "Joe", score: 63, position: "3rd" },
{ name: "Beth", score: 75, position: "4rd" },
{ name: "Kareem", score: 59, position: "5th" },
{ name: "Sarah", score: 93, position: "6th" }
]
const studentObj = studentsArray.reduce((acc, student) => {
return {...acc, [student.name]: student.position}
}, {})
console.log(studentObj)
/*
{
Beth: "4rd",
Jack: "2nd",
Joe: "3rd",
Kareem: "5th",
Kingsley: "1st",
Sarah: "6th"
}
*/
/* Grouping objects by a property */
const result = [
{subject: 'Physics', marks: 41},
{subject: 'Chemistry', marks: 59},
{subject: 'Pure Maths', marks: 36},
{subject: 'Applied Maths', marks: 90},
{subject: 'English', marks: 64},
];
let initialValue = {
pass: [],
fail: []
}
const groupedResult = result.reduce((accumulator, current) => {
(current.marks>=50) ? accumulator.pass.push(current) : accumulator.fail.push(current);
return accumulator;
}, initialValue);
console.log(groupedResult);
/*
{
pass: [
{ subject: ‘Chemistry’, marks: 59 },
{ subject: ‘Applied Maths’, marks: 90 },
{ subject: ‘English’, marks: 64 }
],
fail: [
{ subject: ‘Physics’, marks: 41 },
{ subject: ‘Pure Maths’, marks: 36 }
]
}
*/
/* Reduce is a Higher-Order Function*/
const plusTwoReducer = (acc, cur) => {
acc.push(cur + 2)
return acc
}
const plusSixReducer = (acc, cur) => {
acc.push(cur + 6)
return acc
}
numbers.reduce(plusTwoReducer, [])
numbers.reduce(plusSixReducer, [])
// https://medium.com/@Evelyn.Taylor/rewriting-javascript-converting-an-array-of-objects-to-an-object-7aeaed399017
const people = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
=>
{
1: 'Alice',
2: 'Bob',
3: 'Charlie'
}
// traditional
const peopleObject = {};
for (const person of people) {
peopleObject[person.id] = person.name;
}
console.log(peopleObject); // {1: 'Alice', 2: 'Bob', 3: 'Charlie'}
// better
const peopleObject = people.reduce((acc, person) => {
acc[person.id] = person.name;
return acc;
}, {});
console.log(peopleObject); // {1: 'Alice', 2: 'Bob', 3: 'Charlie'}
// maybe better, maybe less readable, shorter
const peopleObject = people.reduce((acc, { id, name }) => ({ ...acc, [id]: name }), {});