Объект, скопированный во второе свойство через ссылку, сохраняется даже после удаления исходного свойства?
Я думал, что объекты передаются как ссылка. Но когда я удаляю b
, он все еще существует в c
. См. Этот пример:
Эта первая часть имеет смысл для меня, поскольку она передается по ссылке:
var a = {b: {val:true}};
a.c = a.b;
a.b.val = 'rawr';
console.log(uneval(a)); // outputs: "({b:{val:"rawr"}, c:{val:"rawr"}})"
Теперь эта часть не имеет для меня смысла:
var a = {b: {val:true}};
a.c = a.b;
a.b.val = 'rawr';
delete a.b;
console.log(uneval(a)); // outputs: "({c:{val:"rawr"}})"
поэтому свойство b
удаляется, но свойство c
содержит свойства, на которые ссылаются перед удалением. это ошибка в javascript?
изменить:
спасибо всем ответам! поэтому это не ошибка, и это поведение на самом деле очень хорошо, это позволяет людям изменять имена "ключ" / "свойство" при сохранении объекта!:)
Ответы
Ответ 1
Нет, это не ошибка в JavaScript.
Что вы делаете с a.c = a.b
, так это то, что вы создаете еще одну ссылку на один и тот же объект, что означает, что как a.b
, так и a.c
ссылаются на один и тот же под-объект {val: "rawr"}
.
Когда вы выполняете delete a.b
, вы не удаляете под-объект, вы удаляете только свойство a.b
из a
. Это означает, что a.c
будет ссылаться на один и тот же объект.
Если вы также должны удалить свойство a.c
, тогда под-объект будет исчезать.
Ответ 2
... Я опаздываю на вечеринку? Вот мое объяснение (прочитайте другие ответы, это просто, чтобы поддержать эти ответы с визуальным представлением):
- Инициализация пустого объекта
a
другим объектом (value:true
).
![enter image description here]()
- Назначение пустого объекта
a
с помощью свойства b
, относящегося к другому объекту (value:true
).
![enter image description here]()
- Назначение объекта
a
с помощью свойства c
, ссылающегося на тот же объект (value:true
).
![enter image description here]()
- Удаление ключа
b
, поэтому a.b
уже не ссылается на под-объект (value:true
).
![enter image description here]()
- Конечное представление основного объекта
a
.
![enter image description here]()
Таким образом, мы можем легко увидеть наглядное представление о том, как сохранялся под-объект:)
Ответ 3
Следует отметить две вещи: во-первых, как сказано в других ответах, ключевое слово delete удаляет свойство только для объекта, через который вы переходите к доступу к свойству.
Второе, что нужно отметить, это то, что JavaScript не проходит по ссылке, никогда. Он всегда передается как значение, значения иногда ссылаются.
Например:
var a = {
someObject: {}
};
var someObject = a.someObject;
someObject = 'Test';
console.log(a.someObject); // outputs {}
В языке, который проходит по ссылке, это, вероятно, вызовет ошибку, потому что это часто подразумевает сильную переборку переменных.
Ответ 4
Это потому, что:
Оператор delete удаляет свойство из объекта. Удаление MDN
Элемент b
, который соответствует Object {val: true}
, удаляется из a
. Запись c
в a
все еще относится к этому объекту. Если вы попытаетесь удалить c.val
или a.b.val
, вы все равно увидите эффект каскадирования другого.
То, что вы пытаетесь сделать, то есть освобождение данных и ожидание их каскадирования, не происходит в javascript. Если у вас есть фон С++, подумайте о том, что все объекты javascript считаются ссылкой. Ican удалить ссылку на него (т.е. Запись, которая "указывает" на этот объект), но я не могу удалить сам объект. Это чистая прерогатива механизма javascript.
Ответ 5
С этой строкой вы думаете, что c указывает на b:
a.c = a.b;
но на самом деле оба c и b указывают на объект {val: true}, поэтому, если вы удаляете b, объект остается.
вы можете просто подумать, что и c, и b являются просто "меткой", прикрепленной к объекту {val: true}
Ответ 6
Нет, это не ошибка.
Команда delete
не удаляет объект, который ссылается на свойство, он удаляет только свойство. Если объект ссылается из другого места (другое свойство в этом случае), объект все еще жив.
Это то же самое, что и у вас есть две переменные, указывающие на один и тот же объект, и изменение значения одной переменной:
var a = { val: true };
var b = a;
a = null;
console.log(b.val); // b still has a reference to the object