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