Delete a.x vs a.x = undefined

Есть ли существенная разница в выполнении любого из этих?

delete a.x;

против

a.x = undefined;

где

a = {
    x: 'boo'
};

можно сказать, что они эквивалентны?

(Я не принимаю во внимание такие вещи, как V8 не любит delete лучше

Ответ 1

Они не эквивалентны. Основное отличие заключается в том, что настройка

a.x = undefined

означает, что a.hasOwnProperty("x") все еще вернет true, и, следовательно, он все равно будет отображаться в цикле for in и в Object.keys()

delete a.x

означает, что a.hasOwnProperty("x") вернет false

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

if (a.x === undefined)

Чего не следует делать, если вы пытаетесь определить, существует ли свойство, вы всегда должны использовать

// If you want inherited properties
if ('x' in a)

// If you don't want inherited properties
if (a.hasOwnProperty('x'))

Следуя цепочке прототипов (упомянуто zzzzBov) Вызов delete позволит ему идти по цепочке прототипов, тогда как установка значения в undefined не будет искать свойство в цепочке прототипы http://jsfiddle.net/NEEw4/1/

var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
extended.x = "overriding";
console.log(extended.x); // overriding
extended.x  = undefined;
console.log(extended.x); // undefined
delete extended.x;
console.log(extended.x); // fromPrototype

Удаление унаследованных свойств Если свойство, которое вы пытаетесь удалить, является унаследованным, delete не повлияет на него. То есть delete удаляет только свойства самого объекта, а не унаследованные свойства.

var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
delete extended.x;
console.log(extended.x); // Still fromPrototype

Поэтому, если вам нужно убедиться, что значение объекта будет неопределенным, delete не будет работать, когда свойство наследуется, вам придется установить (переопределить) его на undefined в этом случае. Если место, которое проверяет его, не будет использовать hasOwnProperty, но, вероятно, было бы небезопасно предполагать, что везде, где оно проверяет, будет использоваться hasOwnProperty

Ответ 2

Перефразируя вопрос:

Являются ли delete a.x и a.x = undefined эквивалентными?

Нет.

Первая удаляет ключ из переменной, а затем устанавливает ключ со значением undefined. Это имеет значение при повторении свойств объектов и при использовании hasOwnProperty.

a = {
    x: true
};
a.x = undefined;
a.hasOwnProperty('x'); //true
delete a.x;
a.hasOwnProperty('x'); //false

Кроме того, это будет иметь существенное значение, если задействована цепочка прототипов.

function Foo() {
    this.x = 'instance';
}
Foo.prototype = {
    x: 'prototype'
};
a = new Foo();
console.log(a.x); //'instance'

a.x = undefined;
console.log(a.x); //undefined

delete a.x;
console.log(a.x); //'prototype'

Ответ 3

Если a.x является установочной функцией, a.x = undefined будет вызывать функцию, тогда как delete a.x не будет вызывать функцию.

Ответ 4

Имена немного запутаны. a.x = undefined просто устанавливает свойство в undefined, но свойство все еще существует:

> var a = {x: 3};
> a.x = undefined;
> a.constructor.keys(a)
["x"]

delete фактически удаляет его:

> var a = {x: 3};
> delete a.x;
> a.constructor.keys(a)
[]

Ответ 5

Да, есть разница. Если вы используете delete a.x, x больше не является свойством a, но если вы используете a.x=undefined, это свойство, но его значение равно undefined.

Ответ 6

Этот REPL из node должен проиллюстрировать разницу.

> a={ x: 'foo' };
{ x: 'foo' }
> for (var i in a) { console.log(i); };
x
undefined
> a.x=undefined;
undefined
> for (var i in a) { console.log(i); };
x
undefined
> delete a.x;
true
> for (var i in a) { console.log(i); };
undefined

Ответ 7

Я уверен, что вы можете увидеть разницу между var o1 = {p:undefined}; и var o2 = {};.

В обоих случаях o.p будет undefined, но в первом случае это потому, что это значение и во втором случае, потому что нет значения.

delete - это оператор, который позволяет вам получить от o1 (или другого объекта, который имеет значение, присвоенное его свойству p), на o2 следующим образом: delete o1.p;.

Обратная операция выполняется путем простого назначения значения (undefined в этом примере, но это может быть что-то еще) для свойства o1.p = undefined;.

Значит нет, они не эквивалентны.


delete o.p; будет

  • удалите свойство p из объекта, если оно имеет один

  • ничего не делать

o.p = undefined; будет

  • добавьте свойство p к объекту, если он еще не имеет его, и установите его значение undefined

  • просто измените значение свойства, если объект уже имеет его


С точки зрения производительности delete плохо, потому что он изменяет структуру объекта (так же, как добавление нового свойства, если вы не инициализировали его в конструкторе).

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

Ответ 8

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

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

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

Использование undefined вместо ключевого слова delete является плохой практикой, так как оно не освобождает расположение этого ключа в памяти.

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

например,

var a = {};
a.d = undefined;
console.log(a); // this will print { d: undefined }

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

Ответ 9

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

Например, этот код не будет завершен:

let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
    ary.push(y);
    ary[y] = undefined;
    y += 1;
}
console(ary.length);

Выдает эту ошибку:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.

Итак, как вы видите, undefined на самом деле занимает кучу памяти.

Однако, если вы также delete ary-item (вместо того, чтобы просто установить его в undefined), код будет медленно завершаться:

let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
    ary.push(x);
    ary[x] = undefined;
    delete ary[x];
    x += 1;
}
console.log('Success, array-length: ${ary.length}.');

Это крайние примеры, но они указывают на delete, что я нигде не видел упоминаний.