JavaScript中一种特殊的原型继承

JavaScript中一种特殊的原型继承,javascript,Javascript,我在读关于内部[[原型]]链的功能。那么,[[原型]]是做什么的呢?实际上,它是对象链中对象之间的链接器。当我们使用“new”关键字或object.create()函数实例化一个对象时,实际上javascript将该对象的[[Prototype]]链接到另一个对象 因此,我开始实现一些代码来更深入地理解这一点。 我开始创建一个函数并将其用作一个类 var dad= function(){}; dad.prototype.bloodGroup="O+"; 然后我添加了一个子类,如下所示: var

我在读关于内部[[原型]]链的功能。那么,[[原型]]是做什么的呢?实际上,它是对象链中对象之间的链接器。当我们使用“new”关键字或object.create()函数实例化一个对象时,实际上javascript将该对象的[[Prototype]]链接到另一个对象

因此,我开始实现一些代码来更深入地理解这一点。 我开始创建一个函数并将其用作一个类

var dad= function(){};
dad.prototype.bloodGroup="O+";
然后我添加了一个子类,如下所示:

var child= function(){}
child=dad.prototype;
child.name="John";
>    anotherChild
>    Object { bloodGroup="O+",  name="John"}  !!
在下一步中,我添加了另一个名为“anotherChild”的孩子

但令人兴奋的是,当我调用另一个孩子的对象时。具体情况如下:

var child= function(){}
child=dad.prototype;
child.name="John";
>    anotherChild
>    Object { bloodGroup="O+",  name="John"}  !!
因此,这意味着,“另一个孩子”继承自“爸爸””,但它获得了一些与另一个孩子相关的属性,如name=“John”,但这不符合逻辑


有人能说出为什么会发生这种情况,以及Prototype和internal[[Prototype]]属性在链接对象时是如何工作的吗?

执行Prototype继承的正确方法与

child = dad.prototype; // bad
但它是这样做的

child.prototype = new dad(); // good

实际答案是: 当你做
child=dad.prototype
时,
child
现在是
dad
prototype
所以当你做
child.name=“John”
时,你实际上是在做:

dad.prototype.name = "John";
因此,该属性反映在
dad
的所有实例上,但这不是您为另一个孩子
获得此类输出的原因,因为它本质上就是刚刚添加了
name
属性的
dad.prototype


修复?按照本答案第一部分所述的正确方法进行操作。

进行原型继承的正确方法与

child = dad.prototype; // bad
但它是这样做的

child.prototype = new dad(); // good

实际答案是: 当你做
child=dad.prototype
时,
child
现在是
dad
prototype
所以当你做
child.name=“John”
时,你实际上是在做:

dad.prototype.name = "John";
因此,该属性反映在
dad
的所有实例上,但这不是您为另一个孩子
获得此类输出的原因,因为它本质上就是刚刚添加了
name
属性的
dad.prototype

修复?按照本答案第一部分所述的正确方式进行操作。

使用“特殊”一词是正确的,因为它根本无法实现继承(在经典定义中)

每次将
dad.prototype
指定给某个对象时,您只是将一个引用指定给完全相同的对象。在Javascript中分配对象不会复制它。因此,当您修改该对象时,您在任何地方都在修改相同的对象

你所说的“继承”的概念在各个方面都是错误的。您根本没有单独的对象。您拥有的是多个变量,它们都指向同一个原型对象

正确的继承方式如下:

var dad = function(){};
dad.prototype.getBloodGroup = function() {
    return bloodGroup="O+";
};

var child = function(){}      // child constructor
child.prototype = new dad();  // get a copy of a dad object to use as the prototype
var baby = new child();       // create new instance of the child object
baby.name = "John";           // assign property on instance
或者,使用更现代的构造:

var child = function(){}
child.prototype = Object.create(dad.prototype);
var baby = new child();
baby.name = "John";
这样做将创建一个新对象,该对象大致为dad.prototype的副本,并将其分配给子原型。这允许分别修改两个prototype对象,以便将新方法添加到
子.prototype
不会无意中修改
dad.prototype
对象,就像您的方法一样


下面是对代码所做操作的逐步解释:

var dad = function(){};
定义一个名为
dad
的构造函数。仅供参考,现代惯例通常会对构造函数使用大写首字母

dad.prototype.bloodGroup="O+";
var child = function(){}
child = dad.prototype;
anotherChild = dad.prototype;
将属性指定给该函数的原型

dad.prototype.bloodGroup="O+";
var child = function(){}
child = dad.prototype;
anotherChild = dad.prototype;
定义另一个构造函数

dad.prototype.bloodGroup="O+";
var child = function(){}
child = dad.prototype;
anotherChild = dad.prototype;
使
child
变量现在指向
dad.prototype
,这样就替换了
child
构造函数之前的定义,使得前面的语句现在变得毫无意义。所以,现在
child
只是
dad.prototype
的别名。对
child
变量的任何修改也会修改
dad.prototype
,因为两者都指向完全相同的对象

child.name = "John";
将另一个属性添加到
dad.prototype
。这与:

dad.prototype.name = "John";
因此,此时,
child
根本不是对象定义。它只是
dad.prototype
的别名。您根本没有做任何与继承相关的事情

var anotherChild = function(){};
定义另一个构造函数

dad.prototype.bloodGroup="O+";
var child = function(){}
child = dad.prototype;
anotherChild = dad.prototype;
重新定义
anotherChild
变量,使其现在也是
dad.prototype
的别名


因此,最后,当您在控制台中键入另一个孩子时,该变量只指向
dad.prototype
,因此您在控制台中看到的是
dad.prototype的内容转储:

>    anotherChild
>    Object { bloodGroup="O+",  name="John"}  !!
这正是人们所期望的。除了
dad
构造函数和
dad.prototype
之外,您还没有定义任何继承或创建任何对象实例。
child
anotherChild
都只是
dad.prototype
的别名

您的整个代码可以归结为:

var dad = function(){};              // define constructor function
dad.prototype.bloodGroup = "O+";     // add property to dad.prototype
var child = dad.prototype;           // create alias to dad.prototype
dad.prototype = "John";              // add property to dad.prototype
var anotherChild = dad.prototype;    // create another alias to dad.prototype
“古怪”这个词是正确的,因为它根本不能实现继承(在经典定义中)

每次将
dad.prototype
指定给某个对象时,您只是将一个引用指定给完全相同的对象。在Javascript中分配对象不会复制它。因此,当您修改该对象时,您在任何地方都在修改相同的对象

你所说的“继承”的概念在各个方面都是错误的。您根本没有单独的对象。您拥有的是多个变量,它们都指向同一个原型对象

正确的继承方式如下:

var dad = function(){};
dad.prototype.getBloodGroup = function() {
    return bloodGroup="O+";
};

var child = function(){}      // child constructor
child.prototype = new dad();  // get a copy of a dad object to use as the prototype
var baby = new child();       // create new instance of the child object
baby.name = "John";           // assign property on instance
或者,使用更现代的构造