/ Gists / JavaScript

Gists - JavaScript

On gists

Promise / Promise.withResolvers

JavaScript

example.js #

const { promise, resolve, reject } = Promise.withResolvers();

setTimeout(() => resolve('Done!'), 1000);
promise.then(console.log); // 'Done!'



function foo()
{
  const {promise, resolve, reject} = Promise.withResolvers()

  setTimeout(() => {
    resolve('DONE')
  }, 2000)
  
  
  return promise
}


function foo2()
{
  const {promise, resolve, reject} = withResolvers()

  setTimeout(() => {
    resolve('DONE 2')
  }, 2500)
  
  
  return promise
}

// polyfill
function withResolvers() {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  return { promise, resolve, reject };
}

// Použití:
const { promise: aliasOnlyForTesting, resolve } = withResolvers();



(async() => {
  const data = await foo()
  console.log(data)
  
  const data2 = await foo2()
  console.log(data2)
})()


On gists

Lazy loading with IntersectionObserver

JavaScript

image-lazy-loading.js #

document.addEventListener('DOMContentLoaded', () => {
    let lazyImages = document.querySelectorAll('.lazyload');
    let observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                let img = entry.target;
                img.src = img.dataset.src;
                observer.unobserve(img);
            }
        });
    });
    lazyImages.forEach(img => {
        observer.observe(img);
    });
});

On gists

All datatypes in JS for testing

JavaScript

datatypes.js #

// Copied from https://javascript.plainenglish.io/structuredclone-the-easiest-way-to-deep-clone-objects-in-javascript-c503b536266b

const testData = {
  number: 123,
  string: "test",
  undefined: undefined,
  null: null,
  boolean: true,
  object: { a: 1, b: { c: 2 } },
  array: [1, 2, { d: 3 }],
  function: function() { return "hello"; },
  map: new Map([["key1", "value1"], ["key2", "value2"]]),
  set: new Set([1, 2, 3]),
  date: new Date(),
  error: new Error("An error occurred"),
  regex: /test/i,
  domNode: document.createElement("div")
}

On gists

Enum - JS

JavaScript

enum.js #

enum Direction {
  Up,
  Down,
  Left,
  Right
}

const Colors = Object.freeze({
    RED:   Symbol("red"),
    BLUE:  Symbol("blue"),
    GREEN: Symbol("green")
});

/**
 * Enum for common colors.
 * @readonly
 * @enum {{name: string, hex: string}}
 */
const Colors = Object.freeze({
  RED:   { name: "red", hex: "#f00" },
  BLUE:  { name: "blue", hex: "#00f" },
  GREEN: { name: "green", hex: "#0f0" }
});


function createEnum(values) {
  const enumObject = {};
  for (const val of values) {
    enumObject[val] = val;
  }
  return Object.freeze(enumObject);
}

// { Up: 'Up', Down: 'Down', Left: 'Left', Right: 'Right' }
createEnum(['Up', 'Down', 'Left', 'Right']);



class Direction {
  static Up = new Direction('Up');
  static Down = new Direction('Down');
  static Left = new Direction('Left');
  static Right = new Direction('Right');

  constructor(name) {
    this.name = name;
  }
  toString() {
    return `Direction.${this.name}`;
  }
}

On gists

Toggle fn - closure in closure (fn returns fn)

JavaScript

toggle.js #

const toggle = (...list) => 
{
    // To track the cycle.
    let current = -1;
    const length = list.length;
    return function () 
    {
        // Increment current and used modulo to cycle back to the start.
        current = (current + 1) % length;

        // Returing the current element.
        return list[current];
    };
};

const toggleFunction = toggle("ON","OF");
console.log(toggleFunction()); // Prints "ON"
console.log(toggleFunction()); // Prints "OF"
console.log(toggleFunction()); // Prints "ON"

On gists

StructuredClone + set of all datatypes (@fatfish)

JavaScript

copy.js #

// https://javascript.plainenglish.io/structuredclone-the-easiest-way-to-deep-clone-objects-in-javascript-c503b536266b

const testData = {
  number: 123,
  string: "test",
  undefined: undefined,
  null: null,
  boolean: true,
  object: { a: 1, b: { c: 2 } },
  array: [1, 2, { d: 3 }],
  // function: function() { return "hello"; },
  map: new Map([["key1", "value1"], ["key2", "value2"]]),
  set: new Set([1, 2, 3]),
  date: new Date(),
  error: new Error("An error occurred"),
  regex: /test/i,
  // domNode: document.createElement("div")
}

const structuredCloneResult = structuredClone(testData)
console.log(structuredCloneResult)
/*
{
  number: 123,
  string: "test",
  undefined: undefined,
  null: null,
  boolean: true,
  object: { a: 1, b: { c: 2 } },
  array: [1, 2, { d: 3 }],
  function: undefined, // Functions are not cloned
  map: Map { 'key1' => 'value1', 'key2' => 'value2' },
  set: Set { 1, 2, 3 },
  date: 2023-05-23T09:00:00.000Z,
  error: Error: An error occurred,
  regex: /test/i,
  domNode: undefined // DOM nodes are not cloned
}
*/

On gists

Javascript function is object

JavaScript

fn.js #

/*
  function in javascript is object and we can store what ever inside 
*/

function x()
{
  console.log('im x')
}

x.$version = '1.3.21'
x.callback = () => { console.log('what ever')}


console.log(x.$version);
x.callback();

On gists

Baby wolf codes - advanced JS tips

Popular ⭐ JavaScript

tips.js #

// Destructure into multiple variables
const obj = { val: 1 };
const { val: a, val: b, val } = obj;

console.log(a); // -> 1
console.log(b); // -> 1
console.log(val); // ->



// Chaining catch in Promise
const somePromise = async () => Promise.reject('error');
somePromise()
    .then(e => {
        //
    })
    .catch(e => {
        throw new Error('error happened');
    })
    .catch(e => {
        console.log('hi ' + e); // hi Error
    });


// Multiple handlers for Promise
async function add(a, b) {
    return a + b;
}
const promise = add(1, 2);
promise.then(e => `Result 1: ${e}`);
promise.then(e => `Result 2: ${e}`);
// -> Result 1: 3
// -> Result 2: 3



// Mixed promise handler liky try catch
async function someFunction() {
    const res = await somePromise().catch(err => {
        /* handle */
    });
}



// Advanced default params  
function test({ val = -1 } = {}) {
    console.log(val);
}
test(); // -> -1
test({}); // -> -1
test({ val: 123 }); // -> 12


// Generate compact numbers
const formatter = Intl.NumberFormat('en',{ notation: 'compact' });
formatter.format('123'); // -> 123
formatter.format('1234'); // -> 1.2K
formatter.format('1235678'); // -> 1.2M
formatter.format('1235678901'); // -> 1.2B


//Default parameters previously declared
function test(x, y, z = x + y) {
    console.log(z);
}
test(1, 1, 1); // -> 1
test(1, 1); // -> 2



// Additional arguments to setTimeout()
function callback(value) {
    console.log(value);
}
setTimeout(callback, 1000, 5);
// -> Prints '5' after 1 second


// matchMedia
const query = window.matchMedia('(max-width: 600px)');
console.log('init -> ' + +query.matches)
query.addEventListener('change', event => {
console.log('change -> ' + +query.matches)
})


// promises
async function add(a, b) {
return a + b;
}
function addAndDouble(a, b) {
return add(a, b).then(res => res * 2);
}
addAndDouble(1, 2).then(res => {
console.log(res); // -> 6
})

On gists

Proxy object guide

JavaScript

Proxy.js #

// 1)  get + set
const target = {
    name: 'John Smith',
    age: 30,
};
const handler = {
    get: function (target, prop) {
        console.log(`Getting the property ${prop}`);
        return target[prop];
    },
    set: function (target, prop, value) {
        console.log(`Setting the property ${prop} to ${value}`);
        target[prop] = value;
    },
};
const proxy = new Proxy(target, handler);



// 2) with validator fn aka encapsulation
const withValidators = person => {
    const handler = {
        set: function (target, prop, value) {
            if ((prop === 'age' && value < 0) || value > 120) {
                throw new Error('Invalid age');
                return;
            }
            target[prop] = value;
        },
    };

    return new Proxy(person, handler);
};

const person = withValidators({
    name: 'John Smith',
    age: 30,
});



// 3) caching, proxy wrap only function
const cache = {};

const getWeather =  (city) => {
    return "fetch -> city -> " + city
};

const proxiedGetWeather = new Proxy(getWeather, {
    apply(target, thisArg, args)  {
        const city = args[0];

        if (cache[city]) {
            console.log('Loading weather data from cache...');
            return cache[city];
        }

        cache[city] =  target.apply(thisArg, args);
        return cache[city];
    },
});

console.log(proxiedGetWeather('San Francisco'))
console.log(proxiedGetWeather('San Francisco')) // console.log('Loading weather data from cache...');
console.log(proxiedGetWeather('San Francisco')) // console.log('Loading weather data from cache...');


// 4) cannot delete
const handler = {
    deleteProperty(target, key) {
        if (key.startsWith('_')) {
            throw new Error(`Cannot delete internal property '${key}'`);
        }

        delete target[key];
        return true;
    },
};

const user = {
    name: 'John Smith',
    _ssn: 'XXX-YY-ZZZ',
};

const protectedUser = protectInternalProps(user);

// Throw error `Cannot delete internal property '_ssn'`
delete protectedUser._ssn;



// 5 cannot iterate
const handler = {
    ownKeys(target) {
        return Object.keys(target).filter(key => !key.startsWith('_'));
    },
};

const user = {
    name: "John Smith",
    _ssn: "XXX-YY-ZZZ",
};

const protectedUser = protectInternalProps(user);

console.log(Object.keys(protectedUser)); // ['name']

for (let key in protectedUser) {
    console.log(key);
}
// ['name']



// 6) private props in class before exists #privateProps
// https://phuoc.ng/collection/javascript-proxy/implement-private-properties-in-a-javascript-class/
const handler = {
    get(target, key) {
        if (key.startsWith('_')) {
            throw new Error(`Cannot access private property '${key}'`);
        }

        return target[key];
    },
    set(target, key, value) {
        if (key.startsWith('_')) {
            throw new Error(`Cannot modify private property '${key}'`);
        }

        target[key] = value;
        return true;
    },
};

class ProtectedPerson {
    constructor(name, age, ssn) {
        this.name = name;
        this.age = age;
        this._ssn = ssn;

        return new Proxy(this, handler);
    }

    getSsn() {
        return this._ssn;
    }
}

// failed
const person = new ProtectedPerson('John Smith', 42, '123-45-6789');
// Uncaught Error: Cannot access private property '_ssn'
person.getSsn();


// lets improve
const handler = {
    get(target, key) {
        if (key.startsWith('_')) {
            throw new Error(`Cannot access private property '${key}'`);
        }
        const value = target[key];
        return typeof value === 'function' ? value.bind(target) : value;
    },
};

const person = new ProtectedPerson('John Smith', 42, '123-45-6789');
console.log(person.getSsn());   // 123-45-6789



// 7) exists 'in'
const handler = {
    has(target, key) {
        console.log(`Checking for ${key} property...`);
        return key in target;
    },
};

const person = {
    name: 'John Smith',
    age: 42,
    occupation: 'developer',
};

const proxy = new Proxy(person, handler);
// Logs "Checking for name property..." and returns `true`
console.log('name' in proxy);

// Logs "Checking for email property..." and returns `false`
console.log('email' in proxy);


// 9) Reflect API


// AND rest articles and more robust solutions we can found 
// https://phuoc.ng/collection/javascript-proxy/