Всем привет, а я про вас не забыл, просто у нас тут в Африке как-то хуже с интернетом, чем у вас в Европах)
Долгожданный ответ к #Задачка8
Ну первое, что нельзя не прокомментировать - это задание прототипа через свойство
__proto__
, в 2k18 это не очень правильно. Ну, это никогда не было правильно, просто раньше это еще и не работало, а теперь работает, но есть более нормальные способы задать прототип.
Впрочем, очевидно, что к заданию это не относится. И мы были бы не мы, если бы не поумничали, и снисходительно не заметили, что это, конечно, на суть задания не влияет, но в пул реквесте реального проекта мимо проходить нельзя.
Теперь, что там у нас дальше? А дальше происходит удаление свойств из объекта и важно не забыть, как это там работает с прототипами.
Работает очень просто, как и всегда с прототипами нужно помнить: на запись — только собственные свойства, а на чтение — можно и из родителя.
Удаление свойства — это считается как запись.
С первыми тремя консоль логами все просто:
delete obj.a;
console.log(obj.a);
Здесь удаляется собственное свойство
a: 5
, поэтому в консоль выведется значение из прототипа —
10
Потом следует повторение этих двух строк и так как на запись (в нашем случае — удаление) доступны только собственные свойства, то он попыпается удалить то чего уже нет, а в прототип не полезет, потому что нельзя ему, и в консоли мы увидим снова
10
.
Со строчками
delete obj.b;
console.log(obj.b.c);
тоже все ясно, удаляется ссылка на объект
{c: 10}
и при обращении
obj.b.c
— идем в прототип и оттуда считываем
20
.
Ну и самое интересное в этой задачке — последняя пара строк:
delete obj.b.c;
console.log(obj.b.c);
В консоль выведется
undefined
, и получается, что таки можно залезть в прототип и что-то там поменять.
Этот эффект объясняется очень просто: в обращении
obj.b.c
та часть, которая обращается к прототипу
obj.b
делает это на чтение, и мы получаем прямую ссылку на объект и уже из него удаляем собственное свойство
с
.
Когда я разбирал эту задачку в докладе, я написал эквивалентный код:
var temp = obj.b;
delete temp.c;
console.log(obj.b.c);
В нем, мне кажется, хорошо видно, что удаляем мы собственное свойство объекта, а доступ к объекту получили по ссылке из прототипа.