Ответ 1
Прототип - это нормальный объект. Когда объект наследует прототип, он не просто копирует свойства прототипа, но и сохраняет ссылку на прототип.
Вы правы, прототип объекта, это еще один объект, на который ссылается цепочка прототипов.
Разница между двумя вашими фрагментами заключается в том, что с __proto__
вы мутируете прототип food
. Во втором примере вы просто назначаете новый объект, который наследует от more_food
, поэтому food.fruit
разрешен undefined
, потому что ваш исходный объект food
теряется этим назначением.
Что именно делает Object.create?
Object.create
создает новый объект, который наследует объект, переданный в качестве его первого аргумента (он может быть только объектом или null
).
Является ли переменная еда назначенной ссылкой на прототип more_food или Object.create просто возвращает копию объекта more_food?
Ваша переменная food
будет содержать новый объект, который наследует от more_food
, в этой операции нет никакого копирования.
Например:
var food = {fruit:"apple"};
var more_food = Object.create(food, {
vegetable: { value: "celery" }
});
more_food.fruit; // "apple"
more_food.vegetable; // "celery"
В приведенном выше примере more_food
наследуется от food
, другими словами, food
является прототипом more_food
, эта прототипическая ссылка хранится во внутреннем свойстве, называемом [[Prototype]]
. Второй аргумент Object.create
позволяет вам инициализировать свойства этого нового объекта.
Нет копирования, простое делегирование в приведенном выше примере more_food.fruit
доступно через цепочку прототипов, процесс поиска свойств действительно прост, если свойство не найдено на объекте, он снова посмотрел (делегирование! ) на прототипе объекта, рекурсивно, пока не будет найден объект, прототип которого находится null
(например, Object.prototype
).
Итак, more_food.fruit
является наследуемым свойством:
more_food.hasOwnProperty('fruit'); // false, inherited
'fruit' in more_food; // true
Пока vegetable
является собственным свойством more_food
:
more_food.hasOwnProperty('vegetable'); // true
Вышеприведенный пример выглядит так:
+---------------------+ [[Prototype]] +---------------+ | more_food |+--------------->| food | |---------------------| |---------------| | vegetable: "celery" | | fruit: "apple | +---------------------+ +---------------+
Если Object.create просто создает копию, то как работает цепочка прототипов, если переменная пища не имеет ссылки на more_food?
Object.create
не создает копии объектов, он просто устанавливает прототип нового объекта во время его создания.
Имейте в виду, что __proto__
является нестандартной функцией, и в будущем она будет удалена из реализаций, уже указана как устаревшая на Документация Mozilla, основная причина этого, а также почему у языка никогда не может быть способа изменить цепочку прототипов способом __proto__
, так как это вызывает проблемы оптимизации и безопасности на уровне VM и JIT.