feat(bind): Move bind to compat

This commit is contained in:
raon0211 2024-08-09 09:32:42 +09:00
parent 1135f67c06
commit f6be4d7ad6
11 changed files with 140 additions and 65 deletions

View File

@ -122,7 +122,7 @@ function sidebar(): DefaultTheme.Sidebar {
{ text: 'noop', link: '/reference/function/noop' },
{ text: 'ary', link: '/reference/function/ary' },
{ text: 'unary', link: '/reference/function/unary' },
{ text: 'bind', link: '/reference/function/bind' },
{ text: 'bind (compat)', link: '/reference/compat/function/bind' },
],
},
{

View File

@ -133,6 +133,7 @@ function sidebar(): DefaultTheme.Sidebar {
{ text: 'noop', link: '/ko/reference/function/noop' },
{ text: 'ary', link: '/reference/function/ary' },
{ text: 'unary', link: '/reference/function/unary' },
{ text: 'bind (호환성)', link: '/reference/compat/function/unary' },
],
},
{

View File

@ -116,7 +116,7 @@ function sidebar(): DefaultTheme.Sidebar {
{ text: 'noop', link: '/zh_hans/reference/function/noop' },
{ text: 'ary', link: '/zh_hans/reference/function/ary' },
{ text: 'unary', link: '/zh_hans/reference/function/unary' },
{ text: 'bind', link: '/zh_hans/reference/function/bind' },
{ text: 'bind (兼容性)', link: '/zh_hans/reference/function/bind' },
],
},
{

View File

@ -0,0 +1,52 @@
# bind
::: info
이 함수는 [lodash와 완전히 호환](../../../compatibility.md)돼요. `es-toolkit/compat` 라이브러리에서 쓸 수 있어요.
:::
함수의 `this`를 고정하고, `partialArgs`로 미리 인자를 제공해요.
Symbol 타입의 `bind.placeholder`를 쓰면, 미리 제공한 인자가 사용될 위치를 결정할 수 있어요.
내장 `Function#bind` 과는 다르게, 함수의 `length` 프로퍼티는 설정하지 않아요.
## 인터페이스
```typescript
function bind<F extends Function>(func: F, thisObj?: unknown, ...partialArgs: any[]): F;
namespace bind {
placeholder: symbol;
}
```
### 파라미터
- `func` (`F`): `this` 를 고정할 함수.
- `thisObj` (`any`, optional): 함수에 고정될 `this` 객체.
- `partialArgs` (`any[]`): 미리 주어질 인자.
### 반환 값
(`F`): `this`가 고정된 함수.
## 예시
```typescript
import { bind } from 'es-toolkit/compat';
function greet(greeting, punctuation) {
return greeting + ' ' + this.user + punctuation;
}
const object = { user: 'fred' };
let bound = bind(greet, object, 'hi');
bound('!');
// => 'hi fred!'
// Bound with placeholders.
bound = bind(greet, object, bind.placeholder, '!');
bound('hi');
// => 'hi fred!'
```

View File

@ -1,15 +1,20 @@
# bind
Creates a function that invokes `func` with the `this` binding of `thisArg` and `partials` prepended to the arguments it receives.
::: info
This function is fully compatible with lodash. You can find it in our [compatibility library](../../../compatibility.md), `es-toolkit/compat`.
:::
Creates a function that invokes `func` with the `this` binding of `thisObj` and `partials` prepended to the arguments it receives.
The `bind.placeholder` value, which defaults to a `symbol`, may be used as a placeholder for partially applied arguments.
**Note:** Unlike native `Function#bind`, this method doesn't set the `length` property of bound functions.
Note that unlike native `Function#bind`, this method doesn't set the `length` property of bound functions.
## Signature
```typescript
function bind(func: (...args: any[]) => any, thisArg?: any, ...partials: any[]): (...args: any[]) => any;
function bind<F extends Function>(func: F, thisObj?: unknown, ...partialArgs: any[]): F;
namespace bind {
placeholder: symbol;
}
@ -17,18 +22,18 @@ namespace bind {
### Parameters
- `fn` (`(...args: any[]) => any`): The function to bind.
- `thisArg` (`any`, optional): The `this` binding of `func`.
- `partials` (`any[]`): The arguments to be partially applied.
- `func` (`F`): The function to bind.
- `thisObj` (`any`, optional): The `this` binding of `func`.
- `partialArgs` (`any[]`): The arguments to be partially applied.
### Returns
(`(...args: any[]) => any`): Returns the new bound function.
(`F`): Returns the new bound function.
## Examples
```typescript
import { bind } from 'es-toolkit/function';
import { bind } from 'es-toolkit/compat';
function greet(greeting, punctuation) {
return greeting + ' ' + this.user + punctuation;

View File

@ -1,5 +1,10 @@
# bind
::: info
此函数与 lodash 完全兼容。您可以在我们的[兼容性库](../../../compatibility.md)中找到它,`es-toolkit/compat`。
:::
创建一个调用 `func` 的函数,`thisArg` 绑定 `func` 函数中的 `this`,并且 `func` 函数会接收 `partials` 附加参数。
`bind.placeholder` 的值默认是一个 `symbol`,可以用作附加的部分参数的占位符。
@ -28,7 +33,7 @@ namespace bind {
## 示例
```typescript
import { bind } from 'es-toolkit/function';
import { bind } from 'es-toolkit/compat';
function greet(greeting, punctuation) {
return greeting + ' ' + this.user + punctuation;

View File

@ -1,8 +1,8 @@
import { describe, it, expect } from 'vitest';
import { bind } from './bind';
import { isEqual } from '../predicate';
import { isEqual } from '../../predicate/isEqual';
function fn(this: any) {
function fn(this: any, ..._: any[]) {
const result = [this];
// eslint-disable-next-line prefer-rest-params
return result.concat(Array.from(arguments));
@ -79,7 +79,7 @@ describe('bind', () => {
it('should create a function with a `length` of `0`', () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const fn = function (_a: unknown, _b: unknown, _c: unknown) {};
const fn = function (_a: unknown, _b: unknown, _c: unknown) { };
let bound = bind(fn, {});
expect(bound.length).toBe(0);
@ -107,7 +107,7 @@ describe('bind', () => {
return this;
}
function Bar() {}
function Bar() { }
const thisArg = { a: 1 };
const boundFoo = bind(Foo, thisArg) as any;
@ -173,7 +173,7 @@ describe('bind', () => {
it('should not error when calling bound class constructors with the `new` operator', () => {
const createCtor: any = function () {
return class A {};
return class A { };
};
const bound = bind(createCtor()) as any;

View File

@ -0,0 +1,60 @@
/**
* Creates a function that invokes `func` with the `this` binding of `thisArg` and `partials` prepended to the arguments it receives.
*
* The `bind.placeholder` value, which defaults to a `symbol`, may be used as a placeholder for partially applied arguments.
*
* Note: Unlike native `Function#bind`, this method doesn't set the `length` property of bound functions.
*
* @param {(...args: any[]) => any} func The function to bind.
* @param {any} thisArg The `this` binding of `func`.
* @param {any[]} partials The arguments to be partially applied.
* @returns {(...args: any[]) => any} Returns the new bound function.
*
* @example
* function greet(greeting, punctuation) {
* return greeting + ' ' + this.user + punctuation;
* }
* const object = { user: 'fred' };
* let bound = bind(greet, object, 'hi');
* bound('!');
* // => 'hi fred!'
*
* bound = bind(greet, object, bind.placeholder, '!');
* bound('hi');
* // => 'hi fred!'
*/
export function bind<F extends Function>(func: F, thisObj?: unknown, ...partialArgs: any[]): F {
const binded = function (this: any, ...providedArgs: any[]) {
const args: any[] = [];
// Populate args by merging partialArgs and providedArgs.
// e.g.. when we call bind(func, {}, [1, bind.placeholder, 3])(2, 4);
// we have args with [1, 2, 3, 4].
let startIndex = 0;
for (let i = 0; i < partialArgs.length; i++) {
const arg = partialArgs[i];
if (arg === bind.placeholder) {
args.push(providedArgs[startIndex++]);
} else {
args.push(arg);
}
}
for (let i = startIndex; i < providedArgs.length; i++) {
args.push(providedArgs[i]);
}
if (this instanceof binded) {
// @ts-expect-error - fn is a constructor
return new func(...args);
}
return func.apply(thisObj, args);
};
return binded as any as F;
}
bind.placeholder = Symbol('bind.placeholder');

View File

@ -35,6 +35,7 @@ export { zipObjectDeep } from './array/zipObjectDeep.ts';
export { head as first } from '../array/head.ts';
export { ary } from './function/ary.ts';
export { bind } from './function/bind.ts';
export { get } from './object/get.ts';
export { set } from './object/set.ts';

View File

@ -1,48 +0,0 @@
/**
*
* Creates a function that invokes `func` with the `this` binding of `thisArg` and `partials` prepended to the arguments it receives.
*
* The `bind.placeholder` value, which defaults to a `symbol`, may be used as a placeholder for partially applied arguments.
*
* **Note:** Unlike native `Function#bind`, this method doesn't set the `length` property of bound functions.
*
* @param {(...args: any[]) => any} func The function to bind.
* @param {any} thisArg The `this` binding of `func`.
* @param {any[]} partials The arguments to be partially applied.
* @returns {(...args: any[]) => any} Returns the new bound function.
*
* @example
* function greet(greeting, punctuation) {
* return greeting + ' ' + this.user + punctuation;
* }
* const object = { user: 'fred' };
* let bound = bind(greet, object, 'hi');
* bound('!');
* // => 'hi fred!'
*
* bound = bind(greet, object, bind.placeholder, '!');
* bound('hi');
* // => 'hi fred!'
*/
export function bind(func: (...args: any[]) => any, thisArg?: any, ...partials: any[]): (...args: any[]) => any {
const wrapper = function (this: any, ...args: any[]) {
let index = 0;
const result = partials.map(bindArg => {
if (bindArg === bind.placeholder) {
return args[index++];
}
return bindArg;
});
for (let i = index; i < args.length; i++) {
result.push(args[i]);
}
if (this instanceof wrapper) {
// @ts-expect-error - fn is a constructor
return new func(...result);
}
return func.apply(thisArg, result);
};
return wrapper;
}
bind.placeholder = Symbol('bind.placeholder') as symbol;

View File

@ -7,4 +7,3 @@ export { throttle } from './throttle.ts';
export { negate } from './negate.ts';
export { ary } from './ary.ts';
export { unary } from './unary.ts';
export { bind } from './bind.ts';