В javascript есть 8 типов данных, из которых 6 являются примитивными (Number, BigInt, Null, Undefined, String & Boolean), а 2 - непримитивными типами данных (Объекты и символы).

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

Мы можем создать объект двумя способами

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

let me = new Object();

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

let me = {};

Объект содержит свойства (элементы данных, такие как массив, строка, число и т. Д., Что угодно, кроме функций) и методы (функции).

Свойства объекта

Есть 2 типа свойств объекта

я . Свойства данных

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

синтаксис:-

let objectName = {
key1: value1,
key2: value2,
...
};
or
let objectName = {};
objectName.key1 = value1;
objectName[key2] = value2;
...

пример:-

let me = {
name: 'saqib',
age: 18,
};
or
let me = {};
me.name = 'saqib';
me[age] = 18;

Свойства данных помимо значения имеют 3 специальных атрибута / функций / флагов.

а. Возможность записи

Если true, значение свойства можно изменить, в противном случае оно доступно только для чтения.

б. Перечислимый

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

c. Настраиваемый

Если true, свойство может быть удалено, а другие функции свойства (Writable, Enumerable, Value) могут быть изменены, в противном случае - нет.

Когда мы создаем свойство свойство, все 3 из них истинны. Чтобы проверить и изменить эти флаги объекта, мы используем следующие 4 метода: -

1- Object.getOwnPropertyDescriptor ()

Этот метод возвращает объект «дескриптор свойства», который содержит все атрибуты данного свойства.

синтаксис:-

Object.getOwnPropertyDescriptor(objectName, propertyName)

пример:-

let me = {
name: 'saqib',
age: 18,
};
Object.getOwnPropertyDescriptor(me, 'name');
{value: 'saqib', writable: true, enumerable: true, configurable: true}

2- Object.getOwnPropertyDescriptors ()

Этот метод возвращает дескриптор свойства каждого свойства объекта.

синтаксис:-

Object.getOwnPropertyDescriptor(objectName);

пример:-

let me = {
name: 'saqib',
age: 18,
};
Object.getOwnPropertyDescriptors(me);
{
name: {value: 'saqib', writable: true, enumerable: true, configurable: true},
 age: {value: 18, writable: true, enumerable: true, configurable: true}
}

3- Object.defineProperty ()

Если свойство существует, этот метод обновляет свои флаги. В противном случае он создает свойство с заданным значением & flags (здесь, если какой-либо флаг не указан, предполагается, что он имеет значение false)

синтаксис:-

Object.defineProperty(objectName, propertyName, descriptorObject);

пример:-

let me = {
age: 18,
};
Object.defineProperty(me, 'name', {value: 'saqib', writable: true, enumerable: true, configurable: true});
me;
{age: 18, name: 'saqib'}

4- Object.defineProperties ()

Этот метод позволяет нам определять (создавать или изменять) сразу несколько свойств объекта.

синтаксис:-

Object.defineProperties(objectName, {
key1: descriptorObject1,
key2: descriptorObject2,
...
});

пример:-

let me = {};
Object.defineProperties(me, {
name: {value: 'saqib', writable: true, enumerable: true, configurable: true},
age: {value: 18, writable: true, enumerable: true, configurable: true}
});
me;
{name: 'saqib', age: 18}

ii . Свойства аксессуара

Свойства средств доступа имеют настраиваемые и перечисляемые атрибуты, но у них нет атрибутов значения и записи, таких как свойства данных, вместо этого у них есть атрибуты Get & Set. Свойства аксессуара на самом деле являются функциями, но для внешнего кода они кажутся свойствами. Когда вы читаете данные из свойства доступа, вызывается метод Get, а когда вы назначаете данные свойству доступа, вызывается метод Set.

синтаксис:-

let obj = {
   get propName() {
     // getter, the code executed on getting obj.propName
   },
    set propName(value) {
     // setter, the code executed on setting obj.propName = value   
}
 };

пример:-

let user = {
   name: "John",
    get fullName() {
     return this.name;   
},
set fullName(value) {
this.name = value;
}
 };
user.fullName; //John Smith
user.fullName = 'saqib';
user.fullName; //saqib Smith

Объектные методы

Функция внутри объекта называется методом этого объекта.

синтаксис:-

let objectName = {
functionName: function() {...};
}
or
let objectName = {
functionName() {...};
}

пример:-

let me = {
sayHi: function() {console.log('Hi');};
}
or
let me = {
sayHi() {console.log('Hi');};
}

Клонирование объекта

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

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

Мы можем клонировать объект тремя способами;

  1. Использование for в цикле

Цикл for-in перебирает все свойства, ключи которых являются строками (т. е. пропускает те, ключи которых являются символами), включая унаследованные.

синтаксис:-

for (variable in object) { ..code to be executed.. };

На каждой итерации переменной присваивается другое имя свойства.

пример:-

let me = {
name: 'saqib',
age: 18,
};
let clone = {};
for (let key in me) {
clone[key] = me[key];
};

2. Использование метода Object.assign ()

синтаксис:-

Object.assign(targetObject, source1, source2, ...);

пример:-

let me = {
name: 'saqib',
age: 18,
};
let clone = {};
Object.assign(clone, me);

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

При обычном способе клонирования, то есть при использовании цикла for in или метода object.assign () измененные флаги не копируются, а также пропускаются символьные свойства. Мы можем добиться обоих этих целей, используя вместе методы Object.defineProperties () и Object.getOwnPropertyDescriptors ().

синтаксис:-

Object.definedProperties({}, object.getOwnPropertyDescriptors(sourceObjectName));

пример:-

let me = {
name: 'saqib',
age: 18,
};
let clone = Object.definedProperties({}, object.getOwnPropertyDescriptors(me));

Вложенное клонирование

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

let me = {
name: 'saqib',
age: 18, 
him: {name: 'tajamul',age: 20,}
};
let clone = {};
for (let key in me) {
if (typeof me[key] !== 'object') {clone[key] = me[key]}
else {clone[key] = {}; Object.assign(clone[key], me[key]);}
}

Здесь мы исследуем каждый me [ключ], и если это объект, мы копируем его структуру целиком.