2017-01-11 2 views
6

Я смотрел на этот ответ некоторое время, и я не могу обвести вокруг него голову: https://stackoverflow.com/a/23699009/3658800.Почему запись свойств не связана с цепочкой прототипов в Javascript?

Резюмируя:


только свойство считывает поиск по цепочке прототипов, не пишет. Итак, когда вы установили

myObject.prop = '123'; 

Он не смотрит вверх по цепочке, но при установке

myObject.myThing.prop = '123'; 

есть тонкое чтение происходит в этой операции записи, которая пытается искать myThing прежде чем писать в его опору. Вот почему запись в object.properties из дочернего объекта происходит у объектов родителя.


Я в основном прошу кого-то уточнить эту операцию «тонкого чтения». Сначала оценивается myObject.myThing, возвращая ссылку на объект myThing (который затем имеет свой набор свойств «prop»)? Есть ли какой-то источник, где я могу обосновать это (Mozilla, исходный код Javascript и т. Д.)?

+1

js всегда будет смотреть вверх направо, минус одна точка. когда он не может этого сделать, вы получаете ошибку; 'document.xx' в порядке, чтобы попытаться прочитать, потому что от 2-го до правого сегмента является законным. 'document.xx.yy' будет' throw', потому что 'document.xx' является _not_ legal. То же самое относится к любому методу точек, будь то все реквизиты, все протосы или микс. Понятно, почему установка прототипа из пути экземпляра была бы плохой идеей, поэтому JS использует только прототип для инициализации и фасада. – dandavis

+0

Простой ответ: «потому что они просто не делают». Установка значения свойства объекта всегда влияет только на целевой объект. – Pointy

+1

Я думаю, что этот ответ говорит о проблемах при наследовании от вложенных объектов (https://stackoverflow.com/questions/10131052/crockfords-prototypal-inheritance-issues-with-nested-objects/), т. Е. Когда ' .myThing' наследуется, он будет общим (неожиданно). – Bergi

ответ

4

Внутри этой операции записи происходит тонкое чтение, которое пытается найти myThing, прежде чем писать на его опоре. Вот почему запись в object.properties из дочернего объекта происходит у объектов родителя.

Это не «тонкое» чтение. Это обычное чтение.

obj.prop1.prop2 = "foo" 

Рассчитано как (obj.prop1).prop2 = "foo". Предполагая, что воображаемые read и write примитивы, он выполнен в виде

write(
    read(obj, 'prop1'), 
    'prop2', 
    "foo") 

, если это делает его более четким. Другими словами, во-первых, prop1 - читать от obj. консультируя цепочку прототипов, как это нормально для чтения. Если он найден не в экземпляре, а в цепочке прототипов, то результатом будет prop1 на прототипе.

Следующий, prop2 - комплект на объекте, полученном в результате obj.prop1. Если это будет prop1 на прототипе, тогда свойство prop2 установлено на этом прототипе prop1. Если на экземпляре было найдено prop1, то на этом экземпляре находится имущество prop2.

Здесь нет никаких изменений в базовом принципе, который читает, прослеживая цепочку прототипов, и записи всегда находятся на записываемом объекте (без ссылки на цепочку прототипов).

Обратите внимание, что в этом случае могут возникать незначительные различия при наличии сеттеров и геттеров на прототипе.

Чтобы избежать путаницы с самим собой и другими, лучше избегать хранения данных на прототипе.Подумайте о прототипе как исключительно, или прежде всего, как способ совместного использования методов объектов, созданных на основе этого прототипа. Использование прототипов для хранения данных в идеале должно быть ограничено поистине постоянными данными, которые распределяются между экземплярами.