Skip to content

Commit

Permalink
feat(compat): implement toPlainObject (#879)
Browse files Browse the repository at this point in the history
* feat(compat): implement toPlainObject

* chore: make lint happy
  • Loading branch information
D-Sketon authored Dec 8, 2024
1 parent 99f7611 commit 622102c
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 0 deletions.
23 changes: 23 additions & 0 deletions benchmarks/performance/toPlainObject.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { bench, describe } from 'vitest';
import { toPlainObject as toPlainObjectCompatToolkit_ } from 'es-toolkit/compat';
import { toPlainObject as toPlainObjectLodash_ } from 'lodash';

const toPlainObjectCompatToolkit = toPlainObjectCompatToolkit_;
const toPlainObjectLodash = toPlainObjectLodash_;

describe('toPlainObject', () => {
function Foo() {
this.b = 2;
}

Foo.prototype.c = 3;
const foo = new Foo();

bench('es-toolkit/compat/toPlainObject', () => {
toPlainObjectCompatToolkit(foo);
});

bench('lodash/toPlainObject', () => {
toPlainObjectLodash(foo);
});
});
34 changes: 34 additions & 0 deletions docs/ja/reference/compat/util/toPlainObject.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# toPlainObject

::: info
この関数は互換性のために `es-toolkit/compat` からのみインポートできます。代替可能なネイティブ JavaScript API があるか、まだ十分に最適化されていないためです。

`es-toolkit/compat` からこの関数をインポートすると、[lodash と完全に同じように動作](../../../compatibility.md)します。
:::

`value`を普通のオブジェクトに変換します。`value`の継承された列挙可能な文字列キー属性を普通のオブジェクトの自身の属性に平坦化します。

## インターフェース

```typescript
function toPlainObject(value: any): Record<string, any>;
```

### パラメータ

- `value` (`any`): 変換する値です。

### 戻り値

(`Record<string, any>`): 変換されたオブジェクトを返します。

##

```typescript
function Foo() {
this.b = 2;
}
Foo.prototype.c = 3;

toPlainObject(new Foo()); // => { 'b': 2, 'c': 3 }
```
34 changes: 34 additions & 0 deletions docs/ko/reference/compat/util/toPlainObject.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# toPlainObject

::: info
이 함수는 호환성을 위한 `es-toolkit/compat` 에서만 가져올 수 있어요. 대체할 수 있는 네이티브 JavaScript API가 있거나, 아직 충분히 최적화되지 않았기 때문이에요.

`es-toolkit/compat`에서 이 함수를 가져오면, [lodash와 완전히 똑같이 동작](../../../compatibility.md)해요.
:::

`value`를 일반 객체로 변환해요. `value`의 상속된 열거 가능한 문자열 키 속성을 일반 객체의 속성으로 평평하게 만들어요.

## 인터페이스

```typescript
function toPlainObject(value: any): Record<string, any>;
```

### 파라미터

- `value` (`any`): 변환할 값이에요.

### 반환 값

(`Record<string, any>`): 변환된 객체를 반환해요.

## 예시

```typescript
function Foo() {
this.b = 2;
}
Foo.prototype.c = 3;

toPlainObject(new Foo()); // => { 'b': 2, 'c': 3 }
```
34 changes: 34 additions & 0 deletions docs/reference/compat/util/toPlainObject.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# toPlainObject

::: info
This function is only available in `es-toolkit/compat` for compatibility reasons. It either has alternative native JavaScript APIs or isn’t fully optimized yet.

When imported from `es-toolkit/compat`, it behaves exactly like lodash and provides the same functionalities, as detailed [here](../../../compatibility.md).
:::

Converts value to a plain object flattening inherited enumerable string keyed properties of value to own properties of the plain object.

## Signature

```typescript
function toPlainObject(value: any): Record<string, any>;
```

### Parameters

- `value` (`any`): The value to convert.

### Returns

(`Record<string, any>`): Returns the converted plain object.

## Examples

```typescript
function Foo() {
this.b = 2;
}
Foo.prototype.c = 3;

toPlainObject(new Foo()); // => { 'b': 2, 'c': 3 }
```
34 changes: 34 additions & 0 deletions docs/zh_hans/reference/compat/util/toPlainObjct.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# toPlainObject

::: info
出于兼容性原因,此函数仅在 `es-toolkit/compat` 中提供。它可能具有替代的原生 JavaScript API,或者尚未完全优化。

`es-toolkit/compat` 导入时,它的行为与 lodash 完全一致,并提供相同的功能,详情请见 [这里](../../../compatibility.md)
:::

`value` 转换为一个普通对象,将 `value` 的继承的可枚举字符串键属性展平到普通对象的自有属性中。

## 签名

```typescript
function toPlainObject(value: any): Record<string, any>;
```

### 参数

- `value` (`any`): 要转换的值。

### 返回值

(`Record<string, any>`): 返回转换后的普通对象。

## 示例

```typescript
function Foo() {
this.b = 2;
}
Foo.prototype.c = 3;

toPlainObject(new Foo()); // => { 'b': 2, 'c': 3 }
```
1 change: 1 addition & 0 deletions src/compat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,5 +218,6 @@ export { toInteger } from './util/toInteger.ts';
export { toLength } from './util/toLength.ts';
export { toNumber } from './util/toNumber.ts';
export { toPath } from './util/toPath.ts';
export { toPlainObject } from './util/toPlainObject.ts';
export { toSafeInteger } from './util/toSafeInteger.ts';
export { toString } from './util/toString.ts';
30 changes: 30 additions & 0 deletions src/compat/util/toPlainObject.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { describe, expect, it } from 'vitest';
import { toPlainObject } from './toPlainObject';
import { args } from '../_internal/args';

describe('toPlainObject', () => {
it('should flatten inherited string keyed properties', () => {
function Foo(this: any) {
this.b = 2;
}
Foo.prototype.c = 3;

// @ts-expect-error - Foo is a constructor
const actual = Object.assign({ a: 1 }, toPlainObject(new Foo()));
expect(actual).toEqual({ a: 1, b: 2, c: 3 });
});

it('should convert `arguments` objects to plain objects', () => {
const actual = toPlainObject(args);
const expected = { 0: 1, 1: 2, 2: 3 };

expect(actual).toEqual(expected);
});

it('should convert arrays to plain objects', () => {
const actual = toPlainObject(['a', 'b', 'c']);
const expected = { 0: 'a', 1: 'b', 2: 'c' };

expect(actual).toEqual(expected);
});
});
35 changes: 35 additions & 0 deletions src/compat/util/toPlainObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { keysIn } from '../object/keysIn.ts';

/**
* Converts value to a plain object flattening inherited enumerable string keyed properties of value to own properties of the plain object.
*
* @param {any} value The value to convert.
* @returns {Record<string, any>} Returns the converted plain object.
*
* @example
* function Foo() {
* this.b = 2;
* }
* Foo.prototype.c = 3;
* toPlainObject(new Foo()); // { b: 2, c: 3 }
*/
export function toPlainObject(value: any): Record<string, any> {
const plainObject: Record<string, any> = {};
const valueKeys = keysIn(value);

for (let i = 0; i < valueKeys.length; i++) {
const key = valueKeys[i];
const objValue = (value as any)[key];
if (key === '__proto__') {
Object.defineProperty(plainObject, key, {
configurable: true,
enumerable: true,
value: objValue,
writable: true,
});
} else {
plainObject[key] = objValue;
}
}
return plainObject;
}

0 comments on commit 622102c

Please sign in to comment.