Какова цель оператора delete в Javascript?


поведение оператора delete, кажется очень сложно и есть много недоразумений о том, что он на самом деле делает. Мне кажется, что переназначение что-то undefined будет более надежно делать то, что вы ожидаете.

Я никогда не видел delete ключевое слово в Javascript фактически используется в коде без примера, и мне интересно, особенно ли это полезно для чего-либо. тут delete имеют любую цель, которая не может быть достигнута путем переназначения к undefined? используется ли он вообще в любой из известных библиотек (например, jQuery, dojo, backbone и т. д.)?

6 54

6 ответов:

имеет ли удаление какую-либо цель, которая не может быть достигнута путем переназначения на undefined?

да. Если вы хотите разоблачить свойство из прототипа или вызвать in,hasOwnProperty и for (...in...) чтобы не записывать свойство как существующее тогда delete уместно.

var set = {};

set._x = true;

alert('_x' in set);  // true

set._x = undefined;

alert('_x' in set);  // true

delete set._x;

alert('_x' in set);  // false

EDIT: как объясняет Ти Джей Краудер:

цель delete оператор должен полностью удалить свойство из объекта, в то время как установка свойство к undefined просто устанавливает свойство undefined.

это имеет значение само по себе, но это также имеет значение, когда вы используете наследование, потому что если O происходит от P

var P = { prop: 42 };
var O = Object.create(P);  // P is O's prototype.

при получении O.prop, вы получаете значение prop от O, если O имеет свойство с этим именем (даже если его значение не определено), но если O вообще не имеет свойства, то значение будет извлечено из P.prop вместо.

alert(O.prop);  // "42" since O doesn't have its own prop, but P does.
O.prop = undefined;
alert(O.prop);  // "undefined" since O has its own prop.
delete O.prop;
alert(O.prop);  // "42" since the delete "unmasked" P.prop.

Это все достаточно хорошо понимал. Я подумал, что могу добавить интересную историческую заметку относительно двигателей JScript 1.0-5.0.

в этих оригинальных реализациях Microsoft JScript мы использовали объекты IDispatch в стиле Ole Automation для реализации объектов expando. IDispatch, конечно, работает, связывая имя с" идентификатором отправки", который является просто целым числом. Чтобы вызвать динамически, сначала вы просите объект dispatch предоставить вам идентификатор dispatch, связанный с именем, а затем говорите: "теперь вызовите метод, связанный с этим идентификатором, учитывая эти аргументы".

Это все хорошо и замечательно. Но из требований контракта IDispatch заключается в том, что сопоставление от имени до идентификатора отправки должно быть стабильно в течение всего срока службы объекта. Поэтому, если кто-то говорит "добавить свойство Foo к этому объекту", мы можем решить, что свойство Foo связано с идентификатором отправки 0x1234 в этом объекте. С этого момента каждый раз объект запрашивается идентификатор отправки "Foo", он должен вернуть 0x1234,даже если Foo удаляется и впоследствии добавляется снова. это позволяет вызывающему абоненту поддерживать свой собственный быстрый кэш пар name/dispid, а не всегда спрашивать объект при каждом вызове.

практическим результатом этого является то, что "удалить" никоим образом не уменьшает нагрузку на память объекта в этой реализации! Когда вы удаляете свойство (в исходной реализации), мы должны добавить бит к объекту, помечая этот идентификатор отправки как удаленный, но мы должны сохранить всю информацию о сопряжении имя / идентификатор в случае, если это имя когда-либо вернется. Добавление огромного количества свойств к объекту и последующее их удаление не приводит к сжатию объекта в памяти.

движок JScript, конечно, был полностью переписан с моего времени (за исключением, я считаю, парсера и лексера), поэтому я понятия не имею, есть ли у движка эта необычная причуда. Было бы интересно узнать.

Если у вас

 delete Foo.Bar;

Он полностью удаляет панель свойств из объекта Foo

 Foo.Bar = undefined

просто устанавливает свойство Bar в undefined и Foo.Bar существует

другие ответы объясняют мотивацию delete ключевое слово. Я хотел бы добавить, что по состоянию на 2017 год, браузер освободите память как при удалении свойства, так и при установке свойства в undefined.

рассмотрим такой пример (источник roughSizeOfObject()):

> var obj = {a:42,b:"b"}; roughSizeOfObject(obj)
26
> obj.a = undefined; roughSizeOfObject(obj)
18
> delete obj.a; roughSizeOfObject(obj)
10
> obj.b = undefined; roughSizeOfObject(obj)
8
> delete obj.b; roughSizeOfObject(obj)
0

пример берется из Chrome 61 (64-бит) консоли (обратите внимание, что все символы в String внутренне кодируются как 16-битное целое число без знака).

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

резюме:

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

delete действительно предназначен для свойств, а не переменных как таковых. Броузеры позволит вам уйти с прямой переменной удаления, но это не очень хорошая идея и не будет работать в строгом пятом издании ECMAScript режим. Если вы хотите освободить ссылку на что-то, так что это может быть собранный мусор, было бы более обычным сказать variable= null.

Ну, вы бы в конечном итоге с элементом в свой объект, который содержит значение undefined. Ключ не будет.