Ключи объекта могут быть строками или Symbol, а значения — любыми типами данных.
const obj = {
// Ключи (автоматически преобразуются в строки)
"string": "значение",
42: "число как ключ",
true: "булево как ключ",
// Значения (любые типы)
name: "строка",
age: 25,
isActive: true,
items: [1, 2, 3],
nested: { a: 1 },
method: function() { return "функция"; }
};
// Symbol как ключ
const sym = Symbol('id');
obj[sym] = "Symbol значение";Важные особенности:
Строки — естественный тип для ключей объекта:
const obj = {
"firstName": "Иван",
"last-name": "Петров",
"age in years": 30,
"": "пустая строка тоже валидна",
" ": "пробел как ключ",
"123": "строка из чисел"
};
console.log(obj["firstName"]); // "Иван"
console.log(obj["last-name"]); // "Петров"
console.log(obj[""]); // "пустая строка тоже валидна"Числа автоматически преобразуются в строки:
const obj = {
42: "значение",
3.14: "пи",
0: "ноль",
-5: "отрицательное"
};
// Все числовые ключи становятся строками
console.log(obj["42"]); // "значение"
console.log(obj[42]); // "значение" (тоже работает)
console.log(typeof Object.keys(obj)[0]); // "string"
// Проверка преобразования
console.log("42" in obj); // true
console.log(42 in obj); // true (автопреобразование)Boolean значения тоже преобразуются в строки:
const obj = {
true: "истина",
false: "ложь"
};
console.log(obj["true"]); // "истина"
console.log(obj[true]); // "истина"
console.log(obj["false"]); // "ложь"
console.log(obj[false]); // "ложь"
// Ключи стали строками
console.log(Object.keys(obj)); // ["true", "false"]Даже undefined и null становятся строками:
const obj = {
undefined: "не определено",
null: "пустота"
};
console.log(obj["undefined"]); // "не определено"
console.log(obj[undefined]); // "не определено"
console.log(obj["null"]); // "пустота"
console.log(obj[null]); // "пустота"Symbol — единственный тип ключа, который НЕ преобразуется в строку:
const sym1 = Symbol('id');
const sym2 = Symbol('id');
const sym3 = Symbol.for('global');
const obj = {
[sym1]: "первый символ",
[sym2]: "второй символ",
[sym3]: "глобальный символ",
"Symbol(id)": "это НЕ символ, а строка!"
};
console.log(obj[sym1]); // "первый символ"
console.log(obj[sym2]); // "второй символ"
console.log(obj["Symbol(id)"]); // "это НЕ символ, а строка!"
// Symbol ключи не появляются в Object.keys()
console.log(Object.keys(obj)); // ["Symbol(id)"]
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(id), Symbol(id), Symbol(global)]Объекты как ключи преобразуются через toString():
const obj1 = { name: "объект1" };
const obj2 = { name: "объект2" };
const arr = [1, 2, 3];
const container = {
[obj1]: "значение для obj1",
[obj2]: "значение для obj2", // Перезапишет предыдущее!
[arr]: "значение для массива"
};
// Все объекты стали "[object Object]"
console.log(Object.keys(container)); // ["[object Object]", "1,2,3"]
console.log(container[obj1]); // "значение для obj2" (!)
console.log(container["[object Object]"]); // "значение для obj2"Любые примитивы могут быть значениями:
const primitives = {
stringValue: "строка",
numberValue: 42,
booleanValue: true,
undefinedValue: undefined,
nullValue: null,
symbolValue: Symbol('value'),
bigintValue: 123n
};Объекты, массивы и другие сложные типы:
const complex = {
array: [1, 2, 3],
object: { nested: true },
date: new Date(),
regexp: /pattern/gi,
map: new Map([['key', 'value']]),
set: new Set([1, 2, 3]),
weakMap: new WeakMap(),
promise: Promise.resolve("готово")
};Функции — полноценные значения объектов:
const withFunctions = {
// Обычная функция
regularFunction: function() {
return "обычная функция";
},
// Стрелочная функция
arrowFunction: () => "стрелочная функция",
// Метод (сокращенный синтаксис)
method() {
return "метод объекта";
},
// Async функция
async asyncMethod() {
return "асинхронный метод";
},
// Generator функция
*generatorMethod() {
yield "генератор";
}
};DOM элементы, классы и другие специальные объекты:
const special = {
// DOM элемент (в браузере)
element: document.createElement('div'),
// Конструктор класса
MyClass: class MyClass {
constructor(name) {
this.name = name;
}
},
// Error объект
error: new Error("что-то пошло не так"),
// Buffer (в Node.js)
// buffer: Buffer.from('hello')
};| Тип ключа | Преобразование | Пример | Результат |
|---|---|---|---|
| string | Без изменений | "key" | "key" |
| number | В строку | 42 | "42" |
| boolean | В строку | true | "true" |
| undefined | В строку | undefined | "undefined" |
| null | В строку | null | "null" |
| Symbol | Без изменений | Symbol('id') | Symbol(id) |
| Object | toString() | {} | "[object Object]" |
| Array | join(’,‘) | [1,2] | "1,2" |
Ключи имеют определенный порядок:
const obj = {
"3": "три",
"1": "один",
"2": "два",
"b": "бэ",
"a": "а"
};
console.log(Object.keys(obj)); // ["1", "2", "3", "b", "a"]
// Числовые ключи сортируются, строковые — по порядку добавленияSymbol ключи имеют особое поведение:
const sym = Symbol('test');
const obj = {
regular: "обычный ключ",
[sym]: "символьный ключ"
};
// Не отображаются в стандартных методах
console.log(Object.keys(obj)); // ["regular"]
console.log(Object.values(obj)); // ["обычный ключ"]
console.log(Object.entries(obj)); // [["regular", "обычный ключ"]]
// Специальные методы для Symbol
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(test)]
console.log(Reflect.ownKeys(obj)); // ["regular", Symbol(test)]// Индексы массивоподобного объекта
const arrayLike = {
0: "первый",
1: "второй",
2: "третий",
length: 3
};
// Конфигурация по ID
const configs = {
1: { name: "dev", debug: true },
2: { name: "prod", debug: false },
999: { name: "test", debug: true }
};const PRIVATE_ID = Symbol('privateId');
const PRIVATE_METHOD = Symbol('privateMethod');
class User {
constructor(name) {
this.name = name;
this[PRIVATE_ID] = Math.random();
}
[PRIVATE_METHOD]() {
return "приватный метод";
}
getId() {
return this[PRIVATE_ID];
}
}
const user = new User("Иван");
console.log(user.name); // "Иван"
console.log(user.getId()); // 0.123456789
console.log(Object.keys(user)); // ["name"] (Symbol ключи скрыты)// Создание объекта с динамическими ключами
function createObject(keyPrefix, values) {
const obj = {};
values.forEach((value, index) => {
obj[`${keyPrefix}_${index}`] = value;
});
return obj;
}
const result = createObject("item", ["a", "b", "c"]);
console.log(result); // { item_0: "a", item_1: "b", item_2: "c" }const prefix = "user";
const id = 123;
const obj = {
// Вычисляемые ключи
[`${prefix}_${id}`]: "значение",
[prefix.toUpperCase()]: "ЗАГЛАВНЫЕ",
[`is${prefix.charAt(0).toUpperCase() + prefix.slice(1)}Active`]: true
};
console.log(obj);
// {
// user_123: "значение",
// USER: "ЗАГЛАВНЫЕ",
// isUserActive: true
// }// ❌ Проблема: все объекты становятся "[object Object]"
const map = {};
const key1 = { id: 1 };
const key2 = { id: 2 };
map[key1] = "значение 1";
map[key2] = "значение 2"; // Перезапишет предыдущее!
console.log(map); // { "[object Object]": "значение 2" }
// ✅ Решение: используйте Map
const map2 = new Map();
map2.set(key1, "значение 1");
map2.set(key2, "значение 2");
console.log(map2.get(key1)); // "значение 1"
console.log(map2.get(key2)); // "значение 2"const sym = Symbol('test');
const obj = {
regular: "обычный",
[sym]: "символьный"
};
// ❌ Symbol ключи теряются при JSON
const json = JSON.stringify(obj);
console.log(json); // {"regular":"обычный"}
const restored = JSON.parse(json);
console.log(restored[sym]); // undefined
// ✅ Учитывайте это при сериализации
function serializeWithSymbols(obj) {
const symbols = Object.getOwnPropertySymbols(obj);
const result = { ...obj };
symbols.forEach(sym => {
result[sym.toString()] = obj[sym];
});
return result;
}// ❌ Неожиданное поведение
const obj = {};
obj[1] = "один";
obj["1"] = "строка один"; // Перезапишет предыдущее!
console.log(obj); // { "1": "строка один" }
// ✅ Будьте внимательны с типами ключей
const safeObj = new Map();
safeObj.set(1, "число один");
safeObj.set("1", "строка один");
console.log(safeObj.get(1)); // "число один"
console.log(safeObj.get("1")); // "строка один"| Особенность | Object | Map |
|---|---|---|
| Типы ключей | string, Symbol | Любые типы |
| Размер | manual | .size |
| Итерация | Object.keys() | for...of |
| Производительность | Оптимизирован для записей | Оптимизирован для частых добавлений/удалений |
| JSON сериализация | Да | Нет (требует преобразования) |
| Прототип | Есть (Object.prototype) | Чистый (Object.create(null)) |
// Когда использовать Object
const config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3
};
// Когда использовать Map
const cache = new Map();
const element1 = document.getElementById('btn1');
const element2 = document.getElementById('btn2');
cache.set(element1, { clicks: 5 });
cache.set(element2, { clicks: 2 });
cache.set("global", { lastUpdate: Date.now() });const obj = {
1: "a",
"1": "b",
true: "c",
"true": "d"
};
console.log(Object.keys(obj).length);const sym = Symbol('key');
const obj = {
[sym]: "symbol value",
key: "string value"
};
console.log(Object.keys(obj));
console.log(Object.getOwnPropertySymbols(obj));const obj1 = { a: 1 };
const obj2 = { b: 2 };
const container = {};
container[obj1] = "first";
container[obj2] = "second";
console.log(Object.keys(container));
console.log(container[obj1]);const obj = {
"2": "два",
"10": "десять",
"1": "один",
"b": "бэ",
"a": "а"
};
console.log(Object.keys(obj));const obj = {
method1: function() { return "method1"; },
method2() { return "method2"; },
method3: () => "method3"
};
console.log(typeof obj.method1);
console.log(obj.method2());
console.log(obj.method3.name);const prefix = "data";
const keys = ["name", "age"];
const obj = {};
keys.forEach((key, index) => {
obj[`${prefix}_${key}`] = `value_${index}`;
});
console.log(Object.keys(obj));
console.log(obj.data_name);// ✅ Используйте Object для конфигураций и записей
const userConfig = {
theme: "dark",
language: "ru",
notifications: true
};
// ✅ Используйте Map для динамических коллекций
const userSessions = new Map();
userSessions.set(userId1, { loginTime: Date.now() });
userSessions.set(userId2, { loginTime: Date.now() - 1000 });// ✅ Symbol для метаданных и приватных свойств
const META_INFO = Symbol('metaInfo');
class Component {
constructor(props) {
Object.assign(this, props);
this[META_INFO] = {
created: Date.now(),
version: "1.0.0"
};
}
getMetaInfo() {
return this[META_INFO];
}
}// ✅ Валидация ключей
function createSafeObject(entries) {
const obj = {};
entries.forEach(([key, value]) => {
// Убеждаемся, что ключ — строка
const safeKey = String(key);
if (safeKey && safeKey !== "undefined" && safeKey !== "null") {
obj[safeKey] = value;
}
});
return obj;
}
const safe = createSafeObject([
["name", "Иван"],
[null, "плохой ключ"], // Будет пропущен
["age", 30]
]);Ключи объекта:
Значения объекта:
Практические выводы:
Понимание работы с ключами и значениями объектов — это основа эффективной работы с данными в JavaScript!
Хочешь больше статей по подготовке к собеседованию? Подпишись на EasyAdvice, добавляй сайт в избранное и прокачивай себя каждый день 💪