Прототип - это обычный объект.Когда объект наследует прототип, он не просто копирует свойства прототипа, он хранит ссылку на прототип.
Вы правы, прототип объекта - это просто еще одинобъект, на который ссылаются через цепочку прототипов.
Разница между вашими двумя фрагментами в том, что с __proto__
вы мутируете прототип food
.Во втором примере вы просто присваиваете новый объект, который наследуется от more_food
, поэтому food.fruit
разрешается в undefined
, потому что ваш исходный объект food
является потерянным этим присваиванием .
Что именно делает Object.create?
Object.create
создает новый объект , который наследует от объекта, переданного в качестве первого аргумента (это может быть только объект или null
).
Переменной food присвоена ссылка на прототип 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 просто делает копию, то как работает цепочка прототипов, если переменная food не имеет ссылки наmore_food?
Object.create
не создает копии объектов, он просто устанавливает прототип нового объекта во время его создания.
Имейте в виду, что __proto__
является стандартная функция , и она будет удалена из реализаций в будущем, она уже указана как устарела в Документация Mozilla , основная причина этого, а также почемуязык, возможно, никогда не сможет изменить цепочку прототипов так, как __proto__
позволяет понять, что это вызывает проблемы оптимизации и безопасности на уровне VM и JIT.