Прототипное наследование Javascript и затенение свойств объекта

var person = { name :"dummy", personal_details: { age : 22, country : "USA" } };

var bob = Object.create(person);

bob.name = "bob";
bob.personal_details.age = 23;


console.log(bob.personal_details === person.personal_details);
// true : since it does not shadow object of prototype object

console.log(bob.name  === person.name);
// false : since it shadows name

////now
bob.personal_details  = {a:1};
console.log(bob.personal_details === person.personal_details); 

/ / false

для объекта Боб пытается переопределить "имя" в собственность человек затем он затеняется в самом Бобе.

но в случае personal_details то же самое правило нарушается.

Мне очень любопытно узнать, почему это так ??

вот ссылка на jsbin : http://jsbin.com/asuzev/1/edit

3 ответов


то, что происходит, можно легко проиллюстрировать несколькими примерами:

доступ к personal_details через цепочку прототипов

var person = { name :"dummy", personal_details: { age : 22, country : "USA" } }
var bob = Object.create(person)

bob.name = "bob"
bob.personal_details.age = 23

, который выводит так:

console.log( bob );
/// { name :"bob", personal_details: { age : 23, country : "USA" } }

console.log( person )
/// { name :"dummy", personal_details: { age : 23, country : "USA" } }

Возраст 23 теперь установлен на объекте person because bob.personal_details прямая ссылка на person.personal_details через цепочку прототипов Боба. Как только вы перейдете вниз по структуре объекта, вы будете работать непосредственно с

  1. тут bob есть свойство под названием personal_details? нет.
  2. тут person есть свойство под названием personal_details? да.
  3. вернуться на ссылку, чтобы { age: 22 } который хранится где-то в памяти.

теперь запускается новый процесс, поскольку каждая часть навигации или назначения объекта является новым запросом для свойства или метода. Итак, теперь у нас personal_details объект мы переключаемся на запрос записи, потому что свойство или переменная слева имели сторону = equals - это всегда задание.

  1. записать значение 123 в собственность age на объекте { age: 22 }

таким образом, исходный запрос можно рассматривать как что-то вроде этого:

(bob.personal_details)            --- read
    (personal_details.age = 123)  --- write

если bob имел собственную собственность personal_details процесс был бы таким же, но целевой объект, на который записывается, был бы другим.


и наконец...

положите вдоль линий вашего вопроса:

его трудно переварить, что свойства объектов-прототипов рассматриваются как READ_ONLY, но если свойство является объектом, то его можно получить и свободно изменять его свойства !! Правильно ли я понимаю ?

Прототипированные свойства, по-видимому, доступны только для чтения, но только при прямом доступе к свойству объекта, который их наследует , потому что эти свойства фактически не существуют на наследуемом объекте вообще. Если перейти к объекту-прототипу сам он тогда может рассматриваться как любой нормальный объект (читать и писать) потому что это именно то, что это - нормальный объект. Это может быть запутанным изначально, но это наследование природы или прототипа, все дело в том, как вы получаете доступ к свойствам, с которыми работаете.


вы не присваиваете свойству bob во втором случае, так как вы могли бы переопределить его?

в случае bob.name = "bob", вы связываете Боба собственные свойства name.

во втором случае, вы не. Вы получаете доступ к personal_details свойство - через прототип. Затем вы назначаете свойству этого объекта все соединение с bob теряется к тому времени.

подумайте об этом так:

bob.personal_details.age = 23;
// equivalent
expr = bob.personal_details;
expr.age = 23; // As you can see, there's no assignment to bob

Это не нарушает никаких правила, потому что дело совсем другое.


я надеюсь, что диаграмма ниже достаточно ясна, но я попытаюсь объяснить вкратце, что происходит.

при создании нового объекта с помощью Object.create вы создаете объект с прототипом первого аргумента метода create. Так вы создаете bob с прототипом, который указывает на person "объект". Все свойства person работает bob через ссылку на образец.

на следующем рисунке вы меняете bob's имя. Сейчас bob Так Просто вы создаете новый slot или property of bob, которая называется name (теперь интерпретатор не будет проверять цепочку прототипов при поиске свойства name он сразу обнаружит, что у Боба есть такое свойство).

в третьем вы меняете bob.personal_details.age что влияет на person.personal_details.age потому что просто это тот же самый объект.

наконец-то вы установили свойство personal_details, теперь bob слот personal_details, это не свойство прототипа, это ссылка на еще один объект - анонимный.

enter image description here