JavaScript - это объектно-ориентированный язык программирования. Однако, в отличие от других объектно-ориентированных языков, таких как C++ и Python, у него нет классов. Вместо этого у JavaScript есть прототипное наследование.
В прототипальных объектно-ориентированных языках программирования у вас есть только объекты.Наследование осуществляется с помощью одного из двух способов:
- Delegation
- Concatenation
Предположим, что у меня есть объект, называемый rectangle
следующим образом:
var rectangle = {
height: 5,
width: 10,
area: function() {
return this.width * this.height;
}
};
Теперь я могу вычислить площадь этот прямоугольник, вызвав rectangle.area
. Однако что, если бы я хотел создать еще один прямоугольник с разными width
и height
? Здесь используется ваша object
функции (эта функция доступна изначально в большинстве интерпретаторов JavaScript в Object.create
):
var rectangle2 = Object.create(rectangle);
rectangle2.height = 10;
rectangle2.width = 20;
alert(rectangle2.area()); // 200
То, что здесь происходит, что объект rectangle2
наследует от объекта rectangle
посредством делегирования. Для того, чтобы помочь вам визуализировать то, что происходит посмотреть на следующей диаграмме:
null
^
| [[Proto]]
|
+-------------------------------+
| Object.prototype |
+-------------------------------+
| ... |
+-------------------------------+
^
| [[Proto]]
|
+-------------------------------+
| rectangle |
+-------------------------------+
| height: 5 |
+-------------------------------+
| width: 10 |
+-------------------------------+
| area: ... |
+-------------------------------+
^
| [[Proto]]
|
+------------------------------+
| rectangle2 |
+------------------------------+
| height: 10 |
+------------------------------+
| width: 20 |
+------------------------------+
Object.create
функция создает объект (rectangle2
), внутренняя [[Proto]]
свойство указывает на объект rectangle
(прототип rectangle2
).
При попытке получить доступ к объекту недвижимости на rectangle2
JavaScript сначала пытается найти недвижимость на rectangle2
. Если он не может найти недвижимость на rectangle2
тогда он пытается найти его на прототипе rectangle2
(т.е. rectangle
) и так далее до тех пор:
- Он не найти недвижимость, в этом случае она возвращает значение, связанное с это свойство.
- Он исчерпывает цепь прототипа (то есть достигает
null
), и в этом случае он возвращает undefined
.
Следовательно, если я попытаюсь получить доступ rectangle2.width
, он вернется 20
. Однако, если я попытаюсь получить доступ к rectangle2.area
, он вернет функцию rectangle.area
вместо undefined
. Это прототипное наследование для вас в двух словах.
Теперь у вас код сначала создать объект u1
:
var u1 = {
name: "adam"
};
Затем вы создаете объект u2
, который наследуется от u1
:
var u2 = Object.create(u1);
После этого вы установили новый name
имущество на u2
(это не перезаписывает name
недвижимость u1
, это просто тени его):
u2.name = "roman";
Затем удалить name
свойство u1
(это не влияет на свойство имени u2
):
delete u1.name;
Так при входе u2.name
он отображает roman
:
console.log(u2.name); // roman
Затем удалить name
свойство из u2
, а также:
delete u2.name;
Поэтому при входе u2.name
снова отображается undefined
:
console.log(u2.name); // undefined
Наконец вы установили u1.name
в tytus
:
u1.name = "tytus";
Поэтому при входе u2.name
снова его отображает tytus
, потому что u2
делегирует u1
:
console.log(u2.name); // tytus
Я надеюсь, что это помогло вам понять прототипичное наследство. Если вы хотите узнать больше, прочитайте мой пост в блоге Why Prototypal Inheritance Matters.
хорошее описание +1 – Vinay