Они не эквивалентны. Основное отличие заключается в том, что настройка
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