Object.freeze и Object.seal в JS
Привет, Хабр!
Сегодня рассмотрим такие инструменты в JS, как Object.freeze
и Object.seal
. С помощью них можно установить надежный контроль над объектами, защитив их от нежелательных изменений.
Как работают Object.freeze и Object.seal
Object.freeze
Object.freeze
предотвращает любые изменения объекта. Это означает, что вы не сможете:
Добавлять новые свойства.
Удалять существующие свойства.
Изменять значения уже существующих свойств.
Посмотрим на пример:
const user = {
name: "Artem",
age: 30
};
Object.freeze(user);
// Попытка изменить существующее свойство
user.age = 31; // Без изменений
// Попытка добавить новое свойство
user.email = "alice@example.com"; // Без изменений
console.log(user); // { name: "Artem", age: 30 }
Как вы видите, все попытки изменить объект не сработали. На низком уровне Object.freeze
добавляет флаг non-configurable
ко всем свойствам объекта, что не позволяет их изменять.
Если есть вложенные объекты, Object.freeze
не замораживает их автоматически. Т.е вложенные свойства все еще могут быть изменены:
const nestedUser = {
name: "Ivan",
address: {
city: "New York"
}
};
Object.freeze(nestedUser);
nestedUser.address.city = "Los Angeles"; // Изменение возможно!
console.log(nestedUser.address.city); // "Los Angeles"
Чтобы заморозить вложенные объекты, придется делать это вручную или написать рекурсивную функцию.
Object.seal
Object.seal
позволяет вам запечатать объект, что предотвращает добавление или удаление свойств, но не мешает изменению значений существующих свойств.
Посмотрим на примере:
const settings = {
theme: "light",
notifications: true
};
Object.seal(settings);
// Попытка изменить существующее свойство
settings.theme = "dark"; // Изменение успешно
// Попытка добавить новое свойство
settings.language = "en"; // Без изменений
// Попытка удалить свойство
delete settings.notifications; // Без изменений
console.log(settings); // { theme: "dark", notifications: true }
Изменение theme
прошло успешно, но мы не получилось ни добавить новое свойство, ни удалить существующее.
Примеры использования
Защита конфигурационных объектов
Конфигурационные объекты — это те сущности, которые задают поведение вашего приложения. Они должны быть стабильными и неизменными, чтобы избежать случайных ошибок:
const config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3
};
Object.freeze(config);
// Функция для получения конфигурации
function getConfig() {
return config;
}
// Пример использования
console.log(getConfig().apiUrl); // "https://api.example.com"
// Попытка изменить конфигурацию
config.apiUrl = "https://api.changed.com"; // Не сработает
console.log(getConfig().apiUrl); // Все еще "https://api.example.com"
Используя Object.freeze
, мы гарантируем, что любые попытки изменить config
будут игнорироваться/
Использование в библиотеке Redux
В Redux иммутабельность состояния — ключ к предсказуемости и простоте отладки. Путем использования Object.freeze
, можно защитить состояние от нежелательных мутаций.
Пример:
const initialState = {
user: null,
loggedIn: false
};
function reducer(state = initialState, action) {
switch (action.type) {
case 'LOGIN':
return Object.freeze({
...state,
user: action.payload,
loggedIn: true
});
case 'LOGOUT':
return Object.freeze(initialState);
default:
return state;
}
}
Здесь \используем Object.freeze
, чтобы убедиться, что каждый раз, когда состояние обновляется, оно остается неизменным.
Пример с React
В React часто возникает необходимость управлять состоянием компонентов. Защита состояния с помощью Object.freeze
может помочь предотвратить ошибки при мутациях данных.
Пример:
import React, { useState } from 'react';
const App = () => {
const [config, setConfig] = useState(Object.freeze({
theme: 'light',
notificationsEnabled: true
}));
const toggleTheme = () => {
// Создаем новый объект вместо изменения существующего
setConfig(prevConfig => Object.freeze({
...prevConfig,
theme: prevConfig.theme === 'light' ? 'dark' : 'light'
}));
};
return (
Текущая тема: {config.theme}
);
};
export default App;
В этом примере мы используем Object.freeze
, чтобы защитить состояние конфигурации.
Защита констант и глобальных переменных
Когда вы работаете с константами, иногда приходится гарантировать, что эти значения не будут случайно изменены. СObject.freeze
можно сделать константы действительно неизменными.
Пример:
const constants = Object.freeze({
MAX_CONNECTIONS: 100,
DEFAULT_TIMEOUT: 3000,
APP_NAME: "MyApp"
});
// Попытка изменить константу
constants.MAX_CONNECTIONS = 200; // Не сработает
console.log(constants.MAX_CONNECTIONS); // 100
В этом примере, даже если кто-то попытается изменить MAX_CONNECTIONS
, изменение не произойдет, и ваше приложение останется стабильным.
Больше про языки программирования эксперты OTUS рассказывают в рамках практических онлайн-курсов. С полным каталогом курсов можно ознакомиться по ссылке.