Прототипное наследование 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
через цепочку прототипов Боба. Как только вы перейдете вниз по структуре объекта, вы будете работать непосредственно с
- тут
bob
есть свойство под названиемpersonal_details
? нет. - тут
person
есть свойство под названиемpersonal_details
? да. - вернуться на ссылку, чтобы
{ age: 22 }
который хранится где-то в памяти.
теперь запускается новый процесс, поскольку каждая часть навигации или назначения объекта является новым запросом для свойства или метода. Итак, теперь у нас personal_details
объект мы переключаемся на запрос записи, потому что свойство или переменная слева имели сторону =
equals - это всегда задание.
- записать значение
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
, это не свойство прототипа, это ссылка на еще один объект - анонимный.