В JavaScript объект представляет собой набор пар ключ-значение, где ключи представляют собой строки (или символы), а значения могут быть любого типа. Это неупорядоченная структура данных, которая может содержать примитивные типы данных, массивы и даже функции. Объекты используются для представления сущностей реального мира и предоставляют способ организации и хранения связанных данных.

Создание объектов в JavaScript

Есть несколько способов создания объектов в JavaScript:

Литералы объекта

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

let person = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "New York",
    state: "NY"
  }
};

Использование конструктора объектов

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

let person = new Object();
person.name = "John";
person.age = 30;
person.address = {
  street: "123 Main St",
  city: "New York",
  state: "NY"
};

Использование Object.create()

Третий способ создания объектов — использование метода Object.create(). Этот метод создает новый объект и устанавливает его прототип в существующий объект. Например:

let person = Object.create(null);
person.name = "John";
person.age = 30;
person.address = {
  street: "123 Main St",
  city: "New York",
  state: "NY"
};

Доступ к свойствам объекта

Вы можете получить доступ к свойствам объекта, используя запись через точку или скобки. Например:

let person = {
  name: "John",
  age: 30
};
console.log(person.name); // "John"
console.log(person["age"]); // 30

Изменение свойств объекта

Вы можете изменить свойства объекта, просто присвоив им новое значение. Например:

let person = {
  name: "John",
  age: 30
};
person.age = 40;
console.log(person.age); // 40

Добавление свойств объекта

Вы можете добавить к объекту новые свойства, просто присвоив значение новому ключу. Например:

let person = {
  name: "John",
  age: 30
};
person.address = {
  street: "123 Main St",
  city: "New York",
  state: "NY"
};
console.log(person.address); // { street: "123 Main St", city: "New York", state: "NY" }

Характеристики ключей и значений в объектах JS

Характеристики ключей и значений в объектах JavaScript следующие:

  1. Ключи должны быть уникальными в пределах объекта. Если вы попытаетесь добавить новое свойство с существующим ключом, значение существующего свойства будет перезаписано новым значением.
  2. Ключи всегда преобразуются в строки. Если вы используете нестроковое значение в качестве ключа, оно будет автоматически преобразовано в строку с помощью метода toString().
  3. Значения могут быть любого типа, включая строки, числа, логические значения, объекты, массивы и функции.
  4. Доступ к значениям можно получить с помощью записи через точку (object.property) или записи в квадратных скобках (object["property"]). Точечная нотация может использоваться только в том случае, если имя свойства является допустимым идентификатором (т. е. оно не содержит пробелов или специальных символов).
  5. Значения можно добавлять или изменять в любое время, присваивая новое значение свойству: object.property = value или object["property"] = value.
  6. Значения также можно удалить с помощью оператора delete: delete object.property или delete object["property"].
  7. В JavaScript обычно не рекомендуется использовать пробелы в имени ключа в объекте. Хотя можно использовать пробелы в именах ключей с использованием записи в квадратных скобках, это может затруднить работу с объектом, так как вам всегда придется использовать запись в квадратных скобках для доступа к свойству.

Например, предположим, что у вас есть объект с ключом под названием «имя», и вы пытаетесь получить к нему доступ, используя запись через точку:

const person = {
  "first name": "John",
  age: 30
};
console.log(person.first name); // Outputs: undefined

Этот код приведет к ошибке, поскольку точечная нотация не допускает пробелов в имени свойства. Вместо этого вам придется использовать нотацию в квадратных скобках для доступа к свойству «имя»:

console.log(person["first name"]); // Outputs: "John"

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

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

для… в цикле

Цикл for…in — полезный инструмент для перебора свойств объекта. Этот цикл позволяет пройтись по всем свойствам объекта и выполнить какое-либо действие над каждым из них. Например:

let person = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "New York",
    state: "NY"
  }
};
for (let prop in person) {
  console.log(prop + ": " + person[prop]);
}
// Output:
// name: John
// age: 30
// address: [object Object]

Ссылка на объект

Когда вы создаете два пустых объекта в JavaScript, они не равны друг другу, хотя оба являются объектами.

Например:

const person1 = {};
const person2 = {};
console.log(person1 == person2); // false

Это связано с тем, что person1 и person2 являются ссылками на разные объекты в памяти, хотя сами объекты не имеют свойств или значений.

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

Вот пример того, как ссылки на объекты работают в JavaScript:

const person1 = { name: "John", age: 30 };
const person2 = person1;

Чтобы сделать копию объекта в JavaScript, вы можете использовать оператор распространения или метод Object.assign():

// Using the spread operator
const person1 = { name: "John", age: 30 };
const person2 = { ...person1 };
person2.age = 31;
console.log(person1.age); // 30

Object.assign() работает следующим образом:

const user = {};
// Using Object.assign() to add a "name" property to the "user" object
Object.assign(user, { name: "john" });
console.log(user); // { name: "john" }

Object.assign также можно использовать для копирования объекта:

// Using Object.assign()
const person3 = { name: "John", age: 30 };
const person4 = Object.assign({}, person3);
person4.age = 31;
console.log(person3.age); // 30

Вывоз мусора

Сборка мусора — это процесс, посредством которого JavaScript автоматически освобождает память, которая больше не используется объектом. Когда объект создается, ему выделяется блок памяти в куче. Когда объект больше не нужен, память освобождается, чтобы ее могли использовать другие объекты.

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

Хотя сборка мусора является полезной функцией JavaScript, она также может иметь некоторые недостатки. Например, управление памятью может быть медленнее, чем в других языках, поскольку сборщику мусора приходится постоянно отслеживать количество ссылок на объекты. Кроме того, сборщик мусора иногда может быть слишком агрессивным, что в некоторых случаях вызывает проблемы с производительностью.

Несмотря на эти ограничения, сборка мусора по-прежнему остается важной функцией JavaScript, которая помогает разработчикам писать более эффективный и надежный код.

// user is reference to object
let user = {
	name: "John"
}
// now reference is overridden
user = null;
// there is no variable pointing to {name: "John"}, it will be in garbage collection

Необязательная цепочка

Необязательная цепочка — это функция JavaScript, позволяющая безопасно получать доступ к глубоко вложенным свойствам объекта, не беспокоясь о промежуточных свойствах null или undefined.

const user = {
  name: "John",
  address: {
    street: "123 Main St",
    city: "Anytown",
    state: "CA",
    zip: "12345"
  }
};
// Using optional chaining to access nested properties
const zipCode = user?.address?.zip; // "12345"
// Trying to access a non-existent property with optional chaining
const phone = user?.contact?.phone; // undefined

Тип символа

В JavaScript Symbol — это примитивный тип данных, который используется для создания уникальных идентификаторов объектов. Символы создаются с помощью функции-конструктора Symbol(), которая при каждом вызове возвращает новый уникальный символ.

Вот пример создания и использования символов с объектом:

const name = Symbol('name');
const age = Symbol('age');
const person = {
  [name]: 'John',
  [age]: 30,
  gender: 'male'
};
console.log(person[name]); // "John"
console.log(person[age]); // 30
console.log(person.gender); // "male"

Мы можем получить доступ к значениям свойств символа, используя обозначение квадратных скобок с символом в качестве ключа. Обратите внимание, что мы не можем получить доступ к свойствам символов, используя запись через точку, поскольку символы не являются допустимыми именами свойств в этом синтаксисе.

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

Символ.iterator

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

Чтобы использовать Symbol.iterator, вы определяете метод для объекта, который возвращает объект итератора. Этот метод вызывается, когда объект используется в цикле for...of или когда метод next() вызывается для объекта-итератора.

Вот пример использования Symbol.iterator для определения итератора для массива:

const arr = [1, 2, 3];
arr[Symbol.iterator] = function() {
  let i = 0;
  return {
    next: () => {
      if (i < this.length) {
        return { value: this[i++], done: false };
      } else {
        return { done: true };
      }
    }
  };
};
for (const num of arr) {
  console.log(num);
}

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

const obj = { from: 1, to: 3 };
obj[Symbol.iterator] = function() {
  let current = this.from;
  const last = this.to;
   return {
    next: () => {
      if (current <= last) {
        return { value: current++, done: false };
      } else {
        return { done: true };
      }
    }
  };
};
const arr = [...obj]; // [1, 2, 3]

Заключение

В JavaScript объекты представляют собой мощную структуру данных, которую можно использовать для представления сложных сущностей. Они обеспечивают способ организации и хранения связанных данных, к ним можно легко получить доступ, изменить и расширить их. Понимание того, как создавать объекты и работать с ними, является важным навыком для любого разработчика JavaScript.