#javascript
Вроде как в коде ниже и всё должно быть просто, но тем не менее принцип работы не поддаётся моему пониманию. При присваивании foo.x = foo = obj, как я понимаю, сначала выполняется правый участок кода, то есть в переменную "foo" заносится ссылка на объект {n:2} из переменной obj, и потом в свойство "foo.x" должна вроде как заноситься аналогичная ссылка, но выходит undefined. Может кто-то объяснить из-за чего подобное происходит? let foo = {}; let obj = {n:2}; foo.x = foo = obj; console.log(foo.x); console.log(foo); console.log(obj);
Ответы
Ответ 1
Другие участники пытаются донести мысль, что при выполнении строки foo.x = foo = obj; имена объектов сначала разыменовываются, как бы заменяются указателями на объекты. Объектов два, давайте обозначим их A и B. Изначально foo указывает на A, obj на B. Тогда та строка превратится в такую последовательность действий: Разыменование, которое превращает foo.x = ... в нечто вроде A.x = ... То, как это устроено, детально поясняет ответ от Igor. Положить в переменную foo ту же ссылку, что в переменной obj. Теперь они обе указывают на B. Положить в поле x объекта A ссылку из переменной foo. Спасибо разыменовыванию. Вот небольшое изменение исходного кода, которое поможет лучше понять ситуацию: let foo = {}; // A let old_foo = foo; // сохраним A let obj = {n:2}; // B foo.x = foo = obj; // foo указывает на B // A.x = *foo = B console.log(foo.x); // B.x = undefined console.log(foo); // B console.log(obj); // B console.log(old_foo); // сохранённное A Как показывает вывод, объект А никуда не делся, просто раньше на него была потеряна ссылка, а присвоение поля x прошло корректно, хоть и не на тот объект, который кажется очевидным.Ответ 2
let holder = { _foo: {} }; Object.defineProperty(holder, 'foo', { get() { return this._foo; }, set(value) { console.log("set foo", value); this._foo = value; } }); Object.defineProperty(holder.foo, 'x', { get() { return this._x; }, set(value) { console.log("set foo.x", value); this._x = value; } }); holder.foo.x = holder.foo = {n:2}; console.log(holder); console.log(holder.foo); Дело в том, что объекты в JS содержат не поля, а свойства. Представьте, что нет свойств, а есть только гетеры и сетеры: holder.getFoo().setX((holder.setFoo({ n: 2 }), holder.getFoo())); Функция setX вызовется, хотя метода setX у результа вызова holder.getFoo в этот момент уже не будет.Ответ 3
Потому что foo.x изначально undefined, а раз выскочил undefined, то js его сразу вернет и продолжит выполнение следующих команд. Так что нужно что-то запихнуть в свойство foo.x. Например вот так let foo = {}; let obj = { n: 2 }; foo.x = obj.n; console.log(foo.x); console.log(foo); console.log(obj);
Комментариев нет:
Отправить комментарий