Skip to content

Commit

Permalink
Refactor bind function to bindSelf
Browse files Browse the repository at this point in the history
  • Loading branch information
shtse8 committed Mar 22, 2024
1 parent 3109ee0 commit 1207841
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export interface CacheOptions {
*
* @example
* class Example {
* const fn = cacheFunc(bind(this)._fn)
* const fn = cacheFunc(bindSelf(this)._fn)
* async _fn() {
* return 'hello'
* }
Expand Down
40 changes: 40 additions & 0 deletions src/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,46 @@ export function bind<Args extends readonly unknown[], T, U>(fn: (this: T, ...arg
return (...args: Args) => fn.call(thisArg, ...args);
}

/**
* Creates a proxy for an object that ensures all its function properties are bound to the object itself.
* This can be particularly useful when you want to pass an object's method as a callback without losing its context.
*
* @param {T} thisArg - The object for which to bind all its function properties.
* @returns {T} A proxy of the same type as `thisArg` where every function property, when accessed,
* is automatically bound to `thisArg`. Non-function properties are accessed as usual.
*
* @example
* ```typescript
* class Example {
* constructor(public name: string) {}
* greet() {
* console.log(`Hello, ${this.name}!`);
* }
* }
*
* const example = new Example('World');
* const boundExample = bindSelf(example);
* const greet = boundExample.greet;
* greet(); // Logs: "Hello, World!" - `this` context is preserved due to binding.
* ```
*
* Note: This function uses JavaScript's Proxy and Reflect APIs to intercept property accesses
* and bind functions dynamically. It works at runtime and relies on TypeScript for type safety only.
* Be cautious that the use of `as T` for the return type is a type assertion that assumes the proxy
* maintains the same type interface as `thisArg`, which TypeScript cannot verify for dynamic property access.
*/
export function bindSelf<T extends object>(thisArg: T): T {
return new Proxy(thisArg, {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver);
if (typeof value === 'function') {
return value.bind(thisArg);
}
return value;
}
}) as T;
}

/**
* Memoizes a function.
* @param fn function to memoize
Expand Down
17 changes: 0 additions & 17 deletions src/typed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,20 +174,3 @@ export function isEmpty(value: any): boolean {
|| (isObject(value) && Object.keys(value).length === 0);
}


/**
* Binds all functions in an object to the object.
* @param thisArg object to bind functions to
* @returns the object with all functions bound
*/
export function bind<T extends object>(thisArg: T): T {
return new Proxy(thisArg, {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver);
if (typeof value === 'function') {
return value.bind(thisArg);
}
return value;
}
}) as T;
}

0 comments on commit 1207841

Please sign in to comment.