Объекты в JS: реализация ссылок на себя в свойствах

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Геттеры идеально подходят для создания вычисляемых свойств в объектах, а фабричные функции – для методов, которые ссылаются на сам объект.

Геттеры для непосредственного взаимодействия со свойствами:

JS
Скопировать код
const obj = {
  a: 1,
  get doubleA() { return this.a * 2; }  // Привет, я – obj, и я удвоил себя! 👋
};
console.log(obj.doubleA);  // Результат: 2

Фабричные функции для создания методов с ссылками на сам объект:

JS
Скопировать код
const createObj = () => {
  let self = { a: 1 };
  self.multiplyA = (x) => self.a * x;  // Зеркальце, скажи, все ли умножили на моё значение a?
  return self;
};
let obj = createObj();
console.log(obj.multiplyA(2));  // Результат: 2

this и self позволяют объекту обратиться к своим собственным свойствам изнутри.

Кинга Идем в IT: пошаговый план для смены профессии

Глубже в тему: усиление самоссылок

Динамическое кэширование свойств через геттеры

Геттеры в ES6 ведут себя подобно волшебникам — они создают динамические объекты, умело кэшируя вычисляемые свойства.

JS
Скопировать код
const dynamicObj = {
  a: 1,
  b: 2,
  get sum() {  // Напоминание к себе: не забыть про солнечный свет.
    const value = this.a + this.b;
    Object.defineProperty(this, 'sum', { value });
    return value;
  }
};
console.log(dynamicObj.sum); // Первый вызов геттера, запоминаем результат.
console.log(dynamicObj.sum); // Второй вызов – получаем сохранённое значение.

Первый вызов sum сохраняет результат, что предотвращает повторные вычисления при обращении к свойству.

Ссылка на самого себя через замыкание функции

Локальная область видимости функции — прекрасный инструмент для создания свойств объекта, ссылками на которые являются сами эти свойства.

JS
Скопировать код
function initializeObj() {
  let obj = { a: 1 };
  obj.b = function() { return this.a + 1; };  // Буква B утверждает, что она знает, как прибавить к A.
  return obj;
}

const obj = initializeObj();
console.log(obj.b()); // Результат: 2. B выдает на гора математическую задачку.

Инициализация объектов "на лету"

Вы можете использовать конструкцию new function() { ... }, чтобы создать и инициализировать объект со свойствами, которые ссылаются на сам объект, непосредственно в коде.

JS
Скопировать код
const obj = new function() {
  this.a = 1;
  this.double = () => this.a * 2;   // Когда A говорит "удвоить", оно это имеет в виду на полном серьезе.
};
console.log(obj.double()); // Результат: 2

Визуализация

На примере эскиза дома легче понять концепцию самоссылающихся свойств в объектах:

Markdown
Скопировать код
Эскиз дома (🏠):

1. Основание: { основной материал: 'бетон' }
2. Стены: { материал: 'кирпич' }
3. Крыша: { стиль: 'мансардная' }

Неудачная попытка самоссылки:
4. Цвет фасада: { цвет: 'такой же, как у стен' } // 🚫 Мы не можем ссылаться на 'Стены' при инициализации!

Функциональный подход:
5. getHouseWithColor() {
   let house = { foundation: 'бетон', walls: 'кирпич', roof: 'мансардная'};
   house.color = { paint: house.walls }; // ✅ Теперь фасад может сослаться на 'Стены'
   return house;
}

Основная заметка: Так же как нельзя принимать 'Стены' за основание при составлении плана, так же в JavaScript нельзя ссылаться на другие свойства во время создания объектного литерала. Но функции позволяют формировать объекты постепенно.

Продвинутое использование ссылок на собственные свойства

Временные свойства и функции для инициализации

Использование временных свойств или функций упрощает процесс инициализации объектов, которые можно затем удалить после того, как они выполнили свою функцию.

JS
Скопировать код
const complexObj = {
  tempFactor: 2,
  a: 1,
  b: 2,
  init() {
    this.c = this.a * this.tempFactor;  // Я — C, я в два раза мощнее, чем A!
    delete this.tempFactor;  // TempFactor ушел на покой
    delete this.init;  // Init также больше не нужен.
    return this;
  }
}.init();
console.log(complexObj); // Результат: { a: 1, b: 2, c: 2 }

Баланс между мощностью и производительностью

Особо сложные механизмы самоссылок могут приводить к уменьшению производительности в приложениях, где важна скорость и лёгкость.

Изменчивость на протяжении жизненного цикла

Разработчик может захотеть добавить или изменить некоторые свойства или методы объекта после его создания:

JS
Скопировать код
let mutableObj = { a: 1 };
mutableObj.b = mutableObj.a * 2;   // B тихим голосом произнесла: "Я – в два раза больше, чем A"
console.log(mutableObj.b); // Результат: 2

Это позволяет вам добавлять свойства к объекту уже после его инициализации, не проводя сложных вычислений.

Полезные материалы

  1. Работа с объектами – JavaScript | MDN — Объекты в JavaScript: ваш путь к званию маэстро.
  2. Легкое объяснение "this" в JavaScript — Прозрачное и понятное разъяснение нюансов работы с this.
  3. Ссылки на объект и их копирование — Мир копирования объектов и ссылок на них, волшебный и могучий, словно из мира Гарри Поттера.
  4. javascript – Ссылки на себя в объектных литералах/инициализаторах – Stack Overflow — Здесь собраны великие знания: дискуссия о самоссылках при инициализации на Stack Overflow.
  5. Создание объектов в JavaScript: шаблоны и лучшие практики — SitePoint — Знание шаблонов создания объектов и лучших практик сделают из вас настоящего ниндзя в этой области.
  6. Понимание области видимости и контекста в JavaScript | Ryan Morr — Войдите в мир областей видимости и контекста в JavaScript и почувствуйте блаженство вследствие новых знаний.
  7. Immediately Invoked Function Expression – Beau teaches JavaScript – YouTubeВидеоуроки о IIFE (немедленно вызываемые функции), для интерактивного обучения.
Свежие материалы