delete 0
Когда выполняется delete 0
, произойдет ли удаление 0
из системы выполнения? Очевидно, нет, истинная цель оператора — удалить ссылку на свойство объекта.
delete object.property
delete object['property']
Как правило, успешное удаление возвращает true
, а неудачное — false
, но есть некоторые исключения.
Собственные свойства
Оператор delete
работает только с собственным свойством объекта. Если в цепочке прототипов окажется свойство с таким же именем, это свойство будет пропущено.
Object.prototype.name = 1; const object = { name: 2, }; // Действует только в отношении собственных свойств. console.log(delete object.name); // true console.log(object.name); // 1 // Но мы можем напрямую манипулировать объектом-прототипом. console.log(delete Object.getPrototypeOf(object).name); // true console.log(object.name); // undefined
Несуществующее свойство
Если удаляемое свойство не существует, delete
не будет иметь никакого эффекта, но все равно вернет true
.
const object = {}; delete object.name; // true
Неконфигурируемое свойство
Неконфигурируемые свойства не могут быть удалены.
const object = {}; Reflect.defineProperty(object, 'name', { configurable: false, }); // Встроенные свойства объекта console.log(delete Math.PI); // false // Неконфигурируемые свойства console.log(delete object.name); // false
В нестрогом режиме удаление неконфигурируемого свойства из самого себя вернет false
, но в строгом режиме оно вызовет TypeError
.
'use strict'; const object = {}; Reflect.defineProperty(object, 'name', { configurable: false, }); // ❌ TypeError: Cannot delete property 'PI' of #<Object> console.log(delete Math.PI); // ❌ TypeError: Cannot delete property 'name' of #<Object> console.log(delete object.name);
Свойства, объявленные с помощью var, let, const
В глобальной области видимости нельзя удалить ни свойства, объявленные с помощью var
, ни функции, объявленные с помощью определения функций (нефункциональных выражений). Это связано с тем, что оба объявленных свойства закреплены за окном и не являются настраиваемыми, поэтому при удалении будет соблюдена логика предыдущего пункта.
Кроме того, свойства, объявленные с помощью var
, let
, const
и этих функций, не могут быть удалены ни в глобальной области видимости, ни в области видимости функции.
{ let object = { name: 1, }; function getName(obj) { return obj.name; } console.log(delete object); // false console.log(delete getName); // false }
В нестрогом режиме возвращается false
, но в строгом режиме, вместо TypeError
, выбрасывается SyntaxError
.
'use strict'; { let object = { name: 1, }; function getName(obj) { return obj.name; } // ❌ SyntaxError: Delete of an unqualified identifier in strict mode. console.log(delete object); // ❌ SyntaxError: Delete of an unqualified identifier in strict mode. console.log(delete getName); }
Свойство массива
Во-первых, свойство length
(длины) массива не является настраиваемым, поэтому его удаление в строгом режиме вызовет TypeError
.
'use strict'; const arr = [1, 2, 3, 4, 5]; console.log(Reflect.getOwnPropertyDescriptor(arr, 'length')); // ❌ TypeError: Cannot delete property 'length' of [object Array] console.log(delete arr.length);
Во-вторых, при удалении элемента массива удаляемый элемент будет пустым.
Чтобы изменить исходный массив, можно использовать Array.prototype.splice()
.
Заключение
Истинное назначение оператора delete
в JavaScript — это удаление ссылки на свойство объекта. В некоторых особых случаях он может вести себя странно, поэтому лучше использовать его только для удаления настраиваемых свойств, присущих самому объекту.
Обратите также внимание на то, что оператор delete
не имеет ничего общего с освобождением памяти напрямую (в отличие от delete в C++). Это связано с тем, что среда выполнения JavaScript управляет памятью автоматически.
Читайте также:
- Javascript и функциональное программирование. Часть 4: каррирование
- Зачем разбивать код на столбцы
- JavaScript Essentials: Типы и структура данных
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Zachary Lee, “The Secret of the ‘delete operator’”