Объекты - это самый фундаментальный тип данных, присутствующий в javascript. В Javascript есть два типа данных. Примитивный тип данных - это неизменяемые типы данных, данные которых хранятся как значения. Другими словами, для любой переменной, содержащей значение примитивного типа данных, всегда будет выделена память. Number, String, Boolean, undefined и null - примитивные типы данных. в javascript. В этой статье мы поймем некоторые основные концепции, связанные с объектами, и как их можно создавать и использовать.

Что такое объекты? Объект - это список элементов, которые хранятся в виде пар "ключ-значение". Значение, хранящееся в объекте, может иметь любой допустимый тип в javascript. Ключи обычно представляют собой строки или числа.

Рассмотрим простой объект:

var simpleObject = { firstName: "Jensen", lastName: "Ackles"};

В этом объекте firstName и lastName являются ключами, а Jensen и Ackles - значениями. Ключи в объекте могут быть strings или numbers. Когда numbers используются в качестве ключей, доступ к значениям должен осуществляться только с использованием скобки.

Данные, сохраненные по значению v / s, сохраненные по ссылке

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

var variable1 = "Data1";
var variable2 = variable1;

variable1 = "Data2";

console.log(variable1); //Data2
console.log(variable2); //Data1

Данные всегда хранятся по значению в примитивных типах. Из-за этого каждой переменной выделено свое место в памяти, и они отличаются друг от друга, даже если они созданы посредством присваивания. Любые изменения, внесенные в одну переменную, не повлияют на другую, если не будет выполнено переназначение.

var variable1 = { name: "Javascript" };
var variable2 = variable1;

variable1.name = "Java";

console.log(variable1.name); //Java
console.log(variable2.name); //Java

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

Атрибуты свойств данных объекта

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

  • Настраиваемый: указывает, можно ли изменить или удалить свойство.
  • Enumerable: указывает, можно ли получить доступ к свойству через цикл for..in.
  • Возможность записи: указывает, можно ли изменить свойство. Эти атрибуты могут использоваться для определения определенных вспомогательных свойств / методов. Например, типу данных array присуще свойство length. Однако это не перечислимое число и часто используется при манипуляциях с массивами. Object.defineProperty можно использовать для установки / изменения этих свойств.
Object.defineProperty( newObject, 'name', {
value: "Jensen Ackles",
writable: true,
enumerable: true,
configurable: true
});

Собственные и унаследованные свойства объектов

Объекты Javascript включают в себя как собственные, так и унаследованные свойства. Собственные свойства - это свойства, которые были определены для объекта, во время его создания или посредством назначения. Унаследованные свойства - это те, которые унаследованы от объекта Prototype объекта.

Чтобы проверить, существует ли свойство у объекта, in можно использовать оператор.

var name = { fullName : "Jensen Ackles" };
console.log("fullName" in name);  // true - The property is its own property
console.log("lastName" in name); // false - The property doesn't exist
console.log("toString" in name); // true - inherited property

Чтобы проверить, имеет ли объект определенное свойство как собственное, мы можем использовать метод hasOwnProperty.

var name = { fullName : "Jensen Ackles" };
console.log(name.hasOwnProperty("fullName"));  // true - The property is its own property
console.log(name.hasOwnProperty("lastName")); // false - The property doesn't exist
console.log(name.hasOwnProperty("toString")); // false - inherited property

Доступ к перечислимым свойствам, связанным с объектом, можно получить с помощью итерации. Для доступа к этим свойствам (собственные / унаследованные) можно использовать цикл for..in или обычный цикл for. Не перечислимые свойства, такие как методы, унаследованные от прототипа объектов, не могут повторяться.

Примитивные способы создания объектов

  1. Литералы объекта. Самый распространенный и простой способ создания объекта - использовать синтаксис литерала объекта.
var movies = {};
var fruits = {
name: "Apple",
color: "red"
}

2. Конструктор объекта. Конструкторы объекта могут использоваться для создания объекта. В этом случае мы создаем пустой объект и начинаем добавлять его свойства.

var movie = new Object();
movie.name = "Memento";
movie.director = "Christopher Nolan";

Есть еще два способа создания объекта: object.create и object.assign. Однако эти методы обычно используются для создания объекта из существующего объекта.

Расширенные способы создания объектов

Более программный способ создания объектов включает использование шаблона конструктор или прототип. Представьте себе сценарий, когда объект имеет определенное базовое свойство, которое постоянно меняется, однако ему также требуются внутренние методы для обработки и управления этими свойствами. Создание дублирующего объекта, состоящего из основных свойств и методов, кажется повторяющимся. Вместо этого мы можем использовать эти расширенные способы создания объектов и создавать новые объекты, используя базовый шаблон (конструктор). Это особенно используется, когда один и тот же объект используется в нескольких местах. Наследование объектов реализуется с использованием этих шаблонов.

  1. Шаблон конструктора: в шаблоне конструктора мы можем определить функцию, которая действует как конструктор, принимая определенные свойства. Внутри него также могут быть определены методы, общие для всех объектов, созданных с помощью этого конструктора.
function Fruits (name, color, value) {
    this.name = name;
    this.color = color;
    this.value = value;

    this.getName = function() {
        return this.name;
    }

    this.getValue = function() {
        return this.value;
    }

    this.changeValue = function(newValue) {
        this.value = newValue
    }
}

Имея базовый конструктор на месте, мы можем определить / создать наш собственный Fruit объект со свойствами, которые нам требуются в любом месте кода, без особого повторения.

var apple = new Fruits("Apple", "red", 20);
console.log(apple.getName()); // Apple
apple.changeValue(50);
console.log(apple.getValue()); // 50

2. Шаблон прототипа: в этом шаблоне исходный объект создается с помощью конструктора. Однако общие методы и свойства могут быть добавлены через свойство prototype объекта.

function Fruits (name, color, value) {
    this.name = name;
    this.color = color;
    this.value = value;
}

Fruits.prototype.getName = function() {
        return this.name;
    }
Fruits.prototype.getValue = function() {
        return this.value;
    }

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

var mango = new Fruits("Mango", "Yello", 70);
console.log(mango.getName()); // Mango
console.log(mango.getValue()); // 70

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

  1. Точечная нотация. Наиболее распространенный способ доступа к свойствам объекта - это точечная нотация. Мы используем . (точка), за которым следует имя свойства, чтобы получить доступ к его значению. Следует отметить, что этот тип доступа работает, только если имена свойств (ключи) strings без пробелов.
var fruits = {
name: "Apple",
color: "red"
}
console.log(fruits.name); // Apple
console.log(fruits.color); // red

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

var fruits = {
name: "Apple",
color: "red"
}
var c = "color";
fruits[1] = "fruit value";
console.log(fruits["name"]); // Apple
console.log(fruits[c]); // red
console.log(fruits[1]); // fruit value

Мелкое копирование против глубокого копирования

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

  1. Неглубокое копирование. Используя Object.assign, неглубокое копирование может быть реализовано, когда мы хотим, чтобы только самый внешний уровень копировался по значению. Объекты могут быть вложенными, и эти вложенные значения по-прежнему будут храниться через ссылку.
var fruit = {
  name: "Apple",
  valueSimple: 20
};
var fruitCopy = Object.assign({}, fruit);

console.log(fruitCopy); // { name: "Apple", valueSimple: 20 }
fruit.valueSimple = 50;
console.log(fruit); // { name: "Apple", valueSimple: 50 }
console.log(fruitCopy); // { name: "Apple", valueSimple: 20 }

Если бы в приведенном выше примере был вложенный объект, изменение значения отразилось бы на всех объектах, созданных с помощью Object.assign.

var fruit = {
  name: "Apple",  
  valueNested: {
      inr: 20
    }
};
var fruitCopy = Object.assign({}, fruit);

console.log(fruitCopy); // { name: "Apple", valueNested: {inr: 20 } }
fruit.valueNested.inr = 50;
console.log(fruit); // { name: "Apple", valueNested: {inr: 50 } }
console.log(fruitCopy); // { name: "Apple", valueNested: {inr: 50 } } - Nested value are stored by reference.

2. Глубокое копирование. Реальные данные могут содержать несколько уровней вложенности. Один из способов полностью скопировать объект без какой-либо ссылки - это пройти через все вложенные уровни и использовать Object.assign. Хотя это утомительно, у нас есть простое решение. Object.parse и JSON.stringify.

var fruit = {
  name: "Apple",  
  valueNested: {
      inr: 20
    }
};
var fruitCopy = JSON.parse(JSON.stringify(fruit));

console.log(fruitCopy); // { name: "Apple", valueNested: {inr: 20 } }
fruit.valueNested.inr = 50;
console.log(fruit); // { name: "Apple", valueNested: {inr: 50 } }
console.log(fruitCopy); // { name: "Apple", valueNested: {inr: 20 } }

Объекты - это первоклассные граждане в javascript. Почти все сложные типы данных, включая функции, создаются на основе Object javascript. Понимание основ создания и использования объектов, безусловно, должно помочь в долгосрочной перспективе.

Первоначально опубликовано на https://aparnajoshi.netlify.app.