Чи є якась істотна різниця у виконанні будь-якого з них?
delete a.x;
проти
a.x = undefined;
де
a = {
x: 'boo'
};
чи можна сказати, що вони рівноцінні?
(Я не беру до уваги такі речі, як "V8 не подобається використовувати deleteкраще" )
Чи є якась істотна різниця у виконанні будь-якого з них?
delete a.x;
проти
a.x = undefined;
де
a = {
x: 'boo'
};
чи можна сказати, що вони рівноцінні?
(Я не беру до уваги такі речі, як "V8 не подобається використовувати deleteкраще" )
Відповіді:
Вони не рівноцінні. Основна відмінність - це налаштування
a.x = undefined
означає, що a.hasOwnProperty("x")все одно повернеться істиною, а отже, вона все одно відображатиметься в for inциклі та вObject.keys()
delete a.x
означає, що a.hasOwnProperty("x")повернеться помилковим
Те, що вони однакові, полягає в тому, що ви не можете визначити, чи існує властивість шляхом тестування
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дозволить йому піднятися по ланцюгу прототипу, тоді як встановлення значення невизначене не буде шукати властивість у ланцюгових прототипах 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
"x" in aповернеться і trueз першим, і falseз останнім. Вихід Object.keysтакож буде різним.
undefined, ви можете просто перевірити if (a.x), якщо це не для цифр і 0, це дійсно
Перефразовуючи питання:
Є
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'
deleteте, щоб дозволити йому піднятися по прототипу
Так, є різниця. Якщо ви використовуєте delete a.xx більше не є властивістю a, але якщо ви використовуєте, a.x=undefinedце властивість, але його значення не визначено.
Я впевнений, що ви можете побачити різницю між 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випускає вміст, але не змушуючи змінювати структуру.
Об'єкт - це просто подання на дерево, тобто корінь в пам'яті вказує на різні місця пам'яті, де зберігаються ключі цього об’єкта. і це місце вказує на інше місце, де зберігається фактичне значення цього ключа, або на місця, де зберігаються дочірні ключі, або на місця, де зберігаються значення масиву.
Коли ви видаляєте будь-який ключ з об'єкта за допомогою видалення, він фактично видаляє зв’язок між цим ключем та його батьківським об'єктом та місцями пам'яті ключа та його значенням, звільняючись для зберігання іншої інформації.
Коли ви намагаєтесь видалити будь-який ключ, встановивши невизначене як його значення, то ви просто встановлюєте його значення, не видаляючи цей ключ. Це означає, що розташування пам'яті ключів все ще пов'язане з її батьківським об'єктом і значенням, якщо ключ не визначений.
Використання невизначеного замість використання ключового слова видалення є поганою практикою, оскільки воно не звільняє місце пам'яті цього ключа.
Навіть якщо ключа немає, і ви встановите його як невизначений, то цей ключ буде створений зі значенням undefined.
напр
var a = {};
a.d = undefined;
console.log(a); // this will print { d: undefined }
delete не може працювати з успадкованими властивостями, оскільки ця властивість не є частиною цього дочірнього об'єкта.
as a general rule of thumb, using 'delete' makes thing slower.та developers.google.com/v8/design To reduce the time required to access JavaScript properties, V8 does not use dynamic lookup to access properties. Instead, V8 dynamically creates hidden classes behind the scenes. In V8, an object changes its hidden class when a new property is added. та нарешті smashingmagazine.com/2012/11/…
Використовуючи масив, замість об'єкта, я можу показати, що для видалення використовується менша кількість пам'яті, ніж невизначена.
Наприклад, цей код не закінчиться:
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архів-елемент (замість того, щоб просто встановити його 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те, що я ніде не бачив, щоб хтось згадував.