Skip to content

Commit 1207841

Browse files
committed
Refactor bind function to bindSelf
1 parent 3109ee0 commit 1207841

File tree

3 files changed

+41
-18
lines changed

3 files changed

+41
-18
lines changed

src/cache.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export interface CacheOptions {
4141
*
4242
* @example
4343
* class Example {
44-
* const fn = cacheFunc(bind(this)._fn)
44+
* const fn = cacheFunc(bindSelf(this)._fn)
4545
* async _fn() {
4646
* return 'hello'
4747
* }

src/function.ts

+40
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,46 @@ export function bind<Args extends readonly unknown[], T, U>(fn: (this: T, ...arg
260260
return (...args: Args) => fn.call(thisArg, ...args);
261261
}
262262

263+
/**
264+
* Creates a proxy for an object that ensures all its function properties are bound to the object itself.
265+
* This can be particularly useful when you want to pass an object's method as a callback without losing its context.
266+
*
267+
* @param {T} thisArg - The object for which to bind all its function properties.
268+
* @returns {T} A proxy of the same type as `thisArg` where every function property, when accessed,
269+
* is automatically bound to `thisArg`. Non-function properties are accessed as usual.
270+
*
271+
* @example
272+
* ```typescript
273+
* class Example {
274+
* constructor(public name: string) {}
275+
* greet() {
276+
* console.log(`Hello, ${this.name}!`);
277+
* }
278+
* }
279+
*
280+
* const example = new Example('World');
281+
* const boundExample = bindSelf(example);
282+
* const greet = boundExample.greet;
283+
* greet(); // Logs: "Hello, World!" - `this` context is preserved due to binding.
284+
* ```
285+
*
286+
* Note: This function uses JavaScript's Proxy and Reflect APIs to intercept property accesses
287+
* and bind functions dynamically. It works at runtime and relies on TypeScript for type safety only.
288+
* Be cautious that the use of `as T` for the return type is a type assertion that assumes the proxy
289+
* maintains the same type interface as `thisArg`, which TypeScript cannot verify for dynamic property access.
290+
*/
291+
export function bindSelf<T extends object>(thisArg: T): T {
292+
return new Proxy(thisArg, {
293+
get(target, prop, receiver) {
294+
const value = Reflect.get(target, prop, receiver);
295+
if (typeof value === 'function') {
296+
return value.bind(thisArg);
297+
}
298+
return value;
299+
}
300+
}) as T;
301+
}
302+
263303
/**
264304
* Memoizes a function.
265305
* @param fn function to memoize

src/typed.ts

-17
Original file line numberDiff line numberDiff line change
@@ -174,20 +174,3 @@ export function isEmpty(value: any): boolean {
174174
|| (isObject(value) && Object.keys(value).length === 0);
175175
}
176176

177-
178-
/**
179-
* Binds all functions in an object to the object.
180-
* @param thisArg object to bind functions to
181-
* @returns the object with all functions bound
182-
*/
183-
export function bind<T extends object>(thisArg: T): T {
184-
return new Proxy(thisArg, {
185-
get(target, prop, receiver) {
186-
const value = Reflect.get(target, prop, receiver);
187-
if (typeof value === 'function') {
188-
return value.bind(thisArg);
189-
}
190-
return value;
191-
}
192-
}) as T;
193-
}

0 commit comments

Comments
 (0)