> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/b-structured/b2-objects/04-object-properties.md).

# 04. Object Properties

## Access to properties

Общий синтаксис:

```javascript
const object = {
  foo: "bar",
  age: 42,
  baz: { myProp: 12 }
};

object.foo; // "bar"
object["age"]; // 42
object.foo = "baz";
```

В JS можно обратиться к любому свойству объекта, даже если его нет. Ошибки не будет. Но если свойство не существует, то вернется `undefined`.

Попытка присвоить значение свойству `p` объекта `o` потерпит неудачу в следующих случаях:

* Объект `o` имеет собственное свойство `p`, доступное только для чтения: нельзя изменить значение свойства, доступного только для чтения.
* Объект `o` имеет унаследованное свойство `p`, доступное только для чтения: унаследованные свойства, доступные только для чтения, невозможно переопределить собственными свойствами с теми же именами.
* Объект `o` не имеет собственного свойства `p`; объект `o` не наследует свойство `p` с методами доступа и атрибут `extensible` объекта o имеет значение `false`.

## Safe property access

Для безопасного доступа к полям объекта можно использовать операторы `||` и `&&` и  `??`. Разница между ними в том, что  `||` и `&&` выполняют более общую проверку на `truthy`/`falsy`, тогда как ??  только на `null` или `undefined`.

```javascript
const o = { x: 1, y: { z: 2 } };
o.x || 3; // 1
o.z || 3; // 3
o.y && o.y.x; // undefined
o.y && o.y.z; // 2
(o.y && o.y.x) || 4; // 4
```

**Optional chaining** в ES2020 позволяет обращаться к вложенным полям объекта при условии, что предыдущие поля в пути определены:

```javascript
// Before
const hashtags = books.entities && books.entities.hashtags

// Optional chaining
const hashtags = books?.entities?.hashtags
```

## Property access in the spec

The operator for getting and setting properties uses the internal operation `ToPropertyKey()`, which works as follows:

* Convert the operand to a primitive via `ToPrimitive()` with the preferred type `String`:
  * A primitive value is returned as it is.
  * Otherwise, the operand is an object. If it has a method `[@@toPrimitive]()`, that method is used to convert it to a primitive value. Symbols have such a method, which returns the wrapped symbol.
  * Otherwise, the operand is converted to a primitive via `toString()` – if it returns a primitive value. Otherwise, `valueOf()` is used – if it returns a primitive value. The preferred type `String` determines that `toString()` is called first, `valueOf()` second.
  * Otherwise, a `TypeError` is thrown.
* If the result of the conversion is a symbol, return it.
* Otherwise, coerce the result to string via `ToString()`.

## Operator `delete`

Единственным способом удалить пару ключ-значение из объекта является оператор `delete`. Если присвоить ключу значение `undefined`, то мы удалим только значение, ключ останется в объекте. Если не использовать `delete`, то ключ будет встречаться при перечислении ключей объекта.

* Оператор `delete` удаляет только собственные свойства и не удаляет унаследованные.
* Нельзя удалить `non-configurable` свойство.
* Чтобы удалить унаследованное свойство, необходимо удалять его в объекте-прототипе, в котором оно определено. Такая операция затронет все объекты, наследующие этот прототип.

```javascript
const mycar = { make: "Honda", model: "Accord", year: 1998 };
delete mycar.make;
"make" in mycar; // returns false
```

Оператор `delete` возвращает `false` если удаляемое свойство является свойством объекта, но не может быть удалено. В остальных случаях оператор возвращает `false`.

На деле, оператор `delete` не связан с управлением памятью. Оператор `delete` полностью удаляет некоторое свойство из указанного объекта, но если оно есть в прототипе -- устанавливается его значение из прототипа. Оператор `delete` позволяет удалять свойства глобального объекта, но не позволяет удалять переменные.

An algorithm for delete is specified roughly like this:

* If operand is not a reference, return `true`
* If object has no direct property with such name, return `true` (where, as we now know, object can be Activation object or Global object)
* If property exists but has `DontDelete`, return `false`

  Otherwise, remove property and return `true`

## Check property existence

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

### Operator `in`

Оператор `in` требует, чтобы в левом операнде ему было передано имя свойства (в виде строки) и объект в правом операнде. Он возвращает `true`, если объект имеет собственное или унаследованное свойство с этим именем. В противном случае возвращает `undefined`.

```javascript
const c = { make: "Honda", model: "Accord", year: 1998 };
"make" in c; // returns true
"model" in c; // returns true
"google" in c; // returns undefined
```

### `obj.hasOwnProperty()`

Метод `hasOwnProperty()` объекта проверяет, имеет ли объект собственное свойство с указанным именем. Для наследуемых свойств он возвращает `false`.

```javascript
const o = {};
o.prop = "exists";
o.hasOwnProperty("prop"); // returns true
o.hasOwnProperty("toString"); // returns false
o.hasOwnProperty("hasOwnProperty"); // returns false
```

### `obj.propertyIsEnumerable()`

Метод `propertyIsEnumerable()` накладывает дополнительные ограничения по сравнению с `hasOwnProperty()`. Он возвращает `true`, только если указанное свойство является собственным свойством, атрибут `enumerable` которого имеет значение `true`.

```javascript
var a = ["is enumerable"];
a.propertyIsEnumerable(0); // returns true
a.propertyIsEnumerable("length"); // returns false
Math.propertyIsEnumerable("random"); // returns false
this.propertyIsEnumerable("Math"); // returns false
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://strctr.gitbook.io/programming/01-languages/javascript/01-language/b-structured/b2-objects/04-object-properties.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
