Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions docs/ja/reference/object/deepFreeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# deepFreeze

オブジェクトを深くフリーズし、すべてのネストされたオブジェクトを不変にします。

`Object.freeze`はオブジェクトの直接のプロパティのみをフリーズしますが、
`deepFreeze`はすべてのネストされたオブジェクトと配列を再帰的にフリーズします。

## インターフェース

```typescript
function deepFreeze<T>(obj: T): T;
```

### パラメータ

- `obj` (`T`): 深くフリーズするオブジェクト。

### 戻り値

(`T`): 深くフリーズされたオブジェクト。

## 例

```typescript
import { deepFreeze } from 'es-toolkit/object';

const frozen = deepFreeze({ user: { name: 'Alex', age: 20 } });

frozen.user = {}; // strictモードではTypeError
frozen.user.age = 22; // strictモードではTypeError
```
31 changes: 31 additions & 0 deletions docs/ko/reference/object/deepFreeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# deepFreeze

객체를 깊게 동결하여 모든 중첩된 객체를 변경 불가능하게 만들어요.

`Object.freeze`는 객체의 직접적인 속성만 동결하지만,
`deepFreeze`는 모든 중첩된 객체와 배열을 재귀적으로 동결해요.

## 인터페이스

```typescript
function deepFreeze<T>(obj: T): T;
```

### 파라미터

- `obj` (`T`): 깊게 동결할 객체예요.

### 반환 값

(`T`): 깊게 동결된 객체를 반환해요.

## 예시

```typescript
import { deepFreeze } from 'es-toolkit/object';

const frozen = deepFreeze({ user: { name: 'Alex', age: 20 } });

frozen.user = {}; // strict 모드에서 TypeError
frozen.user.age = 22; // strict 모드에서 TypeError
```
31 changes: 31 additions & 0 deletions docs/reference/object/deepFreeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# deepFreeze

Deeply freezes an object, making it and all nested objects immutable.

Unlike `Object.freeze`, which only freezes the immediate properties of an object,
`deepFreeze` recursively freezes all nested objects and arrays.

## Signature

```typescript
function deepFreeze<T>(obj: T): T;
```

### Parameters

- `obj` (`T`): The object to deeply freeze.

### Returns

(`T`): The deeply frozen object.

## Examples

```typescript
import { deepFreeze } from 'es-toolkit/object';

const frozen = deepFreeze({ user: { name: 'Alex', age: 20 } });

frozen.user = {}; // TypeError in strict mode
frozen.user.age = 22; // TypeError in strict mode
```
31 changes: 31 additions & 0 deletions docs/zh_hans/reference/object/deepFreeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# deepFreeze

深度冻结对象,使其和所有嵌套的对象都不可变。

与 `Object.freeze` 只冻结对象的直接属性不同,
`deepFreeze` 递归地冻结所有嵌套的对象和数组。

## 签名

```typescript
function deepFreeze<T>(obj: T): T;
```

### 参数

- `obj` (`T`): 要深度冻结的对象。

### 返回值

(`T`): 深度冻结后的对象。

## 示例

```typescript
import { deepFreeze } from 'es-toolkit/object';

const frozen = deepFreeze({ user: { name: 'Alex', age: 20 } });

frozen.user = {}; // 严格模式下抛出 TypeError
frozen.user.age = 22; // 严格模式下抛出 TypeError
```
83 changes: 83 additions & 0 deletions src/object/deepFreeze.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { describe, expect, it } from 'vitest';
import { deepFreeze } from './deepFreeze';

describe('deepFreeze', () => {
it('should freeze nested objects', () => {
const obj = deepFreeze({ user: { name: 'Alex', age: 20 } });

expect(Object.isFrozen(obj)).toBe(true);
expect(Object.isFrozen(obj.user)).toBe(true);
});

it('should freeze nested arrays', () => {
const obj = deepFreeze({ items: [1, 2, { nested: true }] });

expect(Object.isFrozen(obj)).toBe(true);
expect(Object.isFrozen(obj.items)).toBe(true);
expect(Object.isFrozen(obj.items[2])).toBe(true);
});

it('should return the same object', () => {
const obj = { a: 1 };
expect(deepFreeze(obj)).toBe(obj);
});

it('should handle primitives', () => {
expect(deepFreeze(42)).toBe(42);
expect(deepFreeze('hello')).toBe('hello');
expect(deepFreeze(null)).toBe(null);
expect(deepFreeze(undefined)).toBe(undefined);
expect(deepFreeze(true)).toBe(true);
});

it('should handle deeply nested objects', () => {
const obj = deepFreeze({ a: { b: { c: { d: 1 } } } });

expect(Object.isFrozen(obj.a)).toBe(true);
expect(Object.isFrozen(obj.a.b)).toBe(true);
expect(Object.isFrozen(obj.a.b.c)).toBe(true);
});

it('should handle circular references', () => {
const obj: Record<string, any> = { a: 1 };

Check warning on line 42 in src/object/deepFreeze.spec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
obj.self = obj;

const frozen = deepFreeze(obj);

expect(Object.isFrozen(frozen)).toBe(true);
expect(frozen.self).toBe(frozen);
});

it('should handle an empty object', () => {
const obj = deepFreeze({});
expect(Object.isFrozen(obj)).toBe(true);
});

it('should freeze arrays directly', () => {
const arr = deepFreeze([1, [2, 3], { a: 4 }]);

expect(Object.isFrozen(arr)).toBe(true);
expect(Object.isFrozen(arr[1])).toBe(true);
expect(Object.isFrozen(arr[2])).toBe(true);
});

it('should freeze Date and RegExp objects', () => {
const obj = deepFreeze({ date: new Date(), regex: /test/ });

expect(Object.isFrozen(obj.date)).toBe(true);
expect(Object.isFrozen(obj.regex)).toBe(true);
});

it('should prevent modifications in strict mode', () => {
'use strict';
const obj = deepFreeze({ user: { name: 'Alex', age: 20 } });

expect(() => {
(obj as any).user = {};

Check warning on line 76 in src/object/deepFreeze.spec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
}).toThrow();

expect(() => {
(obj as any).user.age = 22;

Check warning on line 80 in src/object/deepFreeze.spec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
}).toThrow();
});
});
35 changes: 35 additions & 0 deletions src/object/deepFreeze.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Deeply freezes an object, making it and all nested objects immutable.
*
* Unlike `Object.freeze`, which only freezes the immediate properties of an object,
* `deepFreeze` recursively freezes all nested objects and arrays.
*
* @template T - The type of the object.
* @param {T} obj - The object to deeply freeze.
* @returns {T} The deeply frozen object.
*
* @example
* const frozen = deepFreeze({ user: { name: "Alex", age: 20 } });
*
* frozen.user = {}; // TypeError in strict mode
* frozen.user.age = 22; // TypeError in strict mode
*/
export function deepFreeze<T>(obj: T): T {
if (obj === null || typeof obj !== 'object') {
return obj;
}

Object.freeze(obj);

const keys = Object.keys(obj) as Array<keyof T>;

for (let i = 0; i < keys.length; i++) {
const value = obj[keys[i]];

if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
deepFreeze(value);
}
}

return obj;
}
1 change: 1 addition & 0 deletions src/object/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { clone } from './clone.ts';
export { cloneDeep } from './cloneDeep.ts';
export { cloneDeepWith } from './cloneDeepWith.ts';
export { deepFreeze } from './deepFreeze.ts';
export { findKey } from './findKey.ts';
export { flattenObject } from './flattenObject.ts';
export { invert } from './invert.ts';
Expand Down
Loading