Daily Practice
Singleton
function singleton(ClassName) {
let instance = null;
return new Proxy(ClassName, {
construct(target, args) {
if (!instance) {
instance = new target(...args);
}
return instance;
},
});
}
Example
const Singleton = singleton(SomeClass);
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2); // true
Proxy can also be used in other things, like
- READ
- Lazy loading
- Log access
- Access control
- Transform value before getting it
- SET
- Validate value before setting it
- Transform value before setting it
- Log access
Write a GCD function
function gcd(a, b) {
while (b) {
let t = b;
b = a % b;
a = t;
}
return a;
}
console.log(gcd(12, 18));
deepClone
function deepClone(obj: unknown) {
if (!obj) return obj;
if (structuredClone) return structuredClone(obj);
if (typeof obj !== "object") return obj;
if (Array.isArray(obj)) {
return obj.map((item) => deepClone(item));
}
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
const cloneObj = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key]);
}
}
return cloneObj;
}
Write a debounce function
function debounce(func: Function, wait: number) {
let timeout: number;
return function (...args) {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
func.apply(this, args);
}, wait);
};
}
Write a throttle function
function throttle(func: Function, wait: number) {
let timeout: number | null;
return function (...args) {
if (!timeout) {
func.apply(this, args);
timeout = setTimeout(() => {
timeout = null;
}, wait);
}
};
}
Write a call function
Function.prototype.myCall = function (context: any, ...args: any[]) {
context = context || window;
const fnSymbol = Symbol("fn");
context[fnSymbol] = this;
const res = context[fnSymbol](...args);
delete context[fnSymbol];
return res;
};
Write an apply function
Function.prototype.myApply = function (context: any, args: any[]) {
context = context || window;
const fnSymbol = Symbol("fn");
context[fnSymbol] = this;
const res = context[fnSymbol](...args);
delete context[fnSymbol];
return res;
};
Write a bind function
Function.prototype.myBind = function (context: any, ...args: any[]) {
context = context || window;
const fnSymbol = Symbol("fn");
context[fnSymbol] = this;
return function (...args2: any[]) {
if (new.target) {
return new context[fnSymbol](...args, ...args2);
}
return context[fnSymbol](...args, ...args2);
};
};
How to find if a function is a generator function
function isGeneratorFunction(fn) {
return fn[Symbol.toStringTag] === "GeneratorFunction";
}
How to find if a function is an async function
function isAsyncFunction(fn) {
return fn[Symbol.toStringTag] === "AsyncFunction";
}
How to find if an object is a proxy object
function isProxyObject(obj) {
return obj[Symbol.toStringTag] === "Proxy";
}
How to find if an object has a specific property
// if you want to check the prototype chain
function hasProperty(obj, prop) {
return Reflect.has(obj, prop);
}
// if you want to check if the property is in the object itself
function hasProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}