JavaScript 是一种面向对象的编程语言。然而,与 C++ 和 Python 等其他面向对象的语言不同,它没有类。相反,JavaScript 具有原型继承。
在原型面向对象的编程语言中,您只有对象。继承是通过以下两种方式之一实现的:
- 代表团
- 级联
假设我有一个名为rectangle
如下的对象:
var rectangle = {
height: 5,
width: 10,
area: function () {
return this.width * this.height;
}
};
现在我可以通过调用来计算这个矩形的面积rectangle.area
。但是,如果我想用不同的width
and创建另一个矩形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
(ie 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
(这不会影响 的 name 属性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
我希望这能帮助你理解原型继承。如果您想了解更多信息,请阅读我关于原型继承为何重要的博文。