0
# Function Utilities
1
2
Function manipulation utilities including binding, throttling, debouncing, and execution control. Perfect for event handling, performance optimization, and creating specialized function behaviors in modern web applications.
3
4
## Capabilities
5
6
### Function Binding
7
8
Utilities for binding functions to specific contexts and pre-applying arguments.
9
10
```javascript { .api }
11
/**
12
* Bind function to specific context with optional pre-applied arguments
13
* @param fn - Function to bind
14
* @param thisArg - Context to bind function to
15
* @param args - Arguments to pre-apply
16
* @returns Bound function
17
*/
18
function bind(fn: Function, thisArg: any, ...args: any[]): Function;
19
```
20
21
### Property Access Functions
22
23
Create functions for accessing object properties.
24
25
```javascript { .api }
26
/**
27
* Create property accessor function
28
* @param path - Property path (string or array)
29
* @returns Function that accesses the specified property
30
*/
31
function property(path: string | string[]): (obj: any) => any;
32
```
33
34
### Execution Control
35
36
Control when and how many times functions execute.
37
38
```javascript { .api }
39
/**
40
* Create function that only executes once
41
* @param fn - Function to execute once
42
* @returns Function that executes only on first call
43
*/
44
function once<T extends (...args: any[]) => any>(fn: T): T;
45
46
/**
47
* Create function that executes only after being called n times
48
* @param count - Number of calls required before execution
49
* @param fn - Function to execute after count calls
50
* @returns Function that tracks call count
51
*/
52
function after(count: number, fn: Function): Function;
53
54
/**
55
* Create function that executes only before being called n times
56
* @param count - Maximum number of executions
57
* @param fn - Function to execute before count reached
58
* @returns Function that stops executing after count
59
*/
60
function before(count: number, fn: Function): Function;
61
```
62
63
### Performance Control
64
65
Throttling and debouncing functions for performance optimization.
66
67
```javascript { .api }
68
/**
69
* Throttle function execution to at most once per wait period
70
* @param fn - Function to throttle
71
* @param wait - Wait time in milliseconds
72
* @param options - Throttling options
73
* @returns Throttled function with cancel method
74
*/
75
function throttle<T extends (...args: any[]) => any>(
76
fn: T,
77
wait: number,
78
options?: ThrottleOptions
79
): T & { cancel(): void };
80
81
interface ThrottleOptions {
82
/** Execute on leading edge (default: true) */
83
leading?: boolean;
84
/** Execute on trailing edge (default: true) */
85
trailing?: boolean;
86
}
87
88
/**
89
* Debounce function execution to occur only after wait period of inactivity
90
* @param fn - Function to debounce
91
* @param wait - Wait time in milliseconds
92
* @param options - Debouncing options
93
* @returns Debounced function with cancel method
94
*/
95
function debounce<T extends (...args: any[]) => any>(
96
fn: T,
97
wait: number,
98
options?: DebounceOptions
99
): T & { cancel(): void };
100
101
interface DebounceOptions {
102
/** Execute on leading edge (default: false) */
103
leading?: boolean;
104
/** Execute on trailing edge (default: true) */
105
trailing?: boolean;
106
}
107
```
108
109
### Delayed Execution
110
111
Utilities for delaying function execution.
112
113
```javascript { .api }
114
/**
115
* Execute function after specified delay
116
* @param fn - Function to execute
117
* @param wait - Delay in milliseconds
118
* @param args - Arguments to pass to function
119
* @returns Timeout ID for cancellation
120
*/
121
function delay(fn: Function, wait: number, ...args: any[]): number;
122
```
123
124
### Utility Functions
125
126
Basic utility functions for common patterns.
127
128
```javascript { .api }
129
/**
130
* No-operation function (does nothing)
131
* @returns undefined
132
*/
133
function noop(): void;
134
```
135
136
**Usage Examples:**
137
138
```javascript
139
import {
140
bind, property, once, after, before, throttle, debounce, delay, noop
141
} from 'xe-utils';
142
143
// Function binding
144
const obj = {
145
name: 'Alice',
146
greet(message) {
147
return `${message}, ${this.name}!`;
148
}
149
};
150
151
const boundGreet = bind(obj.greet, obj);
152
console.log(boundGreet('Hello')); // 'Hello, Alice!'
153
154
// Pre-applying arguments
155
const add = (a, b, c) => a + b + c;
156
const addFive = bind(add, null, 5);
157
console.log(addFive(10, 15)); // 30 (5 + 10 + 15)
158
159
// Property accessor functions
160
const users = [
161
{ name: 'Alice', profile: { age: 25 } },
162
{ name: 'Bob', profile: { age: 30 } }
163
];
164
165
const getName = property('name');
166
const getAge = property(['profile', 'age']);
167
168
console.log(users.map(getName)); // ['Alice', 'Bob']
169
console.log(users.map(getAge)); // [25, 30]
170
171
// Execute once
172
let initCount = 0;
173
const initialize = once(() => {
174
initCount++;
175
console.log('Initializing application...');
176
return 'initialized';
177
});
178
179
console.log(initialize()); // 'Initializing application...' + 'initialized'
180
console.log(initialize()); // 'initialized' (no console output)
181
console.log(initCount); // 1
182
183
// Execute after N calls
184
let setupComplete = false;
185
const completeSetup = after(3, () => {
186
setupComplete = true;
187
console.log('Setup completed after 3 steps!');
188
});
189
190
completeSetup(); // Nothing happens
191
completeSetup(); // Nothing happens
192
completeSetup(); // 'Setup completed after 3 steps!'
193
194
// Execute before N calls
195
const limitedFunction = before(3, (msg) => {
196
console.log(`Message: ${msg}`);
197
});
198
199
limitedFunction('First'); // 'Message: First'
200
limitedFunction('Second'); // 'Message: Second'
201
limitedFunction('Third'); // Nothing happens
202
limitedFunction('Fourth'); // Nothing happens
203
204
// Throttling (limit execution frequency)
205
const expensiveOperation = () => {
206
console.log('Expensive operation executed at', new Date().toISOString());
207
};
208
209
const throttledOperation = throttle(expensiveOperation, 1000);
210
211
// Rapid calls - only executes at most once per second
212
throttledOperation(); // Executes immediately
213
throttledOperation(); // Ignored
214
throttledOperation(); // Ignored
215
setTimeout(throttledOperation, 1100); // Executes after 1 second
216
217
// Debouncing (delay execution until activity stops)
218
const searchAPI = (query) => {
219
console.log('Searching for:', query);
220
// API call here
221
};
222
223
const debouncedSearch = debounce(searchAPI, 300);
224
225
// Typing simulation - only searches after user stops typing
226
debouncedSearch('h'); // Cancelled
227
debouncedSearch('he'); // Cancelled
228
debouncedSearch('hel'); // Cancelled
229
debouncedSearch('hello'); // Executes after 300ms of inactivity
230
231
// Event handler examples
232
function setupEventHandlers() {
233
const button = document.getElementById('save-button');
234
const searchInput = document.getElementById('search-input');
235
const scrollHandler = throttle(() => {
236
console.log('Scroll position:', window.scrollY);
237
}, 100);
238
239
const searchHandler = debounce((event) => {
240
searchAPI(event.target.value);
241
}, 300);
242
243
// Prevent double-clicks on save button
244
const saveHandler = once(() => {
245
console.log('Saving data...');
246
// Save logic here
247
});
248
249
window.addEventListener('scroll', scrollHandler);
250
searchInput.addEventListener('input', searchHandler);
251
button.addEventListener('click', saveHandler);
252
}
253
254
// Delayed execution
255
console.log('Starting delayed operations...');
256
257
delay(() => {
258
console.log('This runs after 1 second');
259
}, 1000);
260
261
delay((name, age) => {
262
console.log(`User: ${name}, Age: ${age}`);
263
}, 2000, 'Alice', 25);
264
265
// Practical throttle/debounce patterns
266
class ResizeHandler {
267
constructor() {
268
this.handleResize = throttle(this.onResize.bind(this), 200);
269
window.addEventListener('resize', this.handleResize);
270
}
271
272
onResize() {
273
console.log('Window resized to:', window.innerWidth, 'x', window.innerHeight);
274
// Update layout logic here
275
}
276
277
destroy() {
278
window.removeEventListener('resize', this.handleResize);
279
this.handleResize.cancel(); // Cancel pending executions
280
}
281
}
282
283
class SearchComponent {
284
constructor() {
285
this.search = debounce(this.performSearch.bind(this), 300);
286
}
287
288
onInput(query) {
289
if (query.length > 2) {
290
this.search(query);
291
} else {
292
this.search.cancel(); // Cancel pending search
293
}
294
}
295
296
async performSearch(query) {
297
console.log('Searching for:', query);
298
// API call implementation
299
}
300
}
301
302
// No-op function for callbacks
303
const optionalCallback = noop; // Safe default callback
304
someAsyncFunction(data, optionalCallback);
305
```