“ 每个对象都有一个私有属性,该属性持有指向另一个称为其原型的对象的链接。该原型对象具有其自己的原型,依此类推,直到到达以null为原型的对象为止。 ,null没有原型,并充当该原型链中的最终链接。“
第一个问题-我希望通过“每个对象都包含原型”,作者的意思是“每个功能对象”都包含 public < strong> prototype 属性,因为像这样的var myObj = {}
对象没有任何 public 原型。
请参见下面的conole屏幕截图-注意使用{}创建的对象的公共原型属性(而不是私有__proto__
)不存在-
第二个问题-在阅读了上述文献后,当我检查了一个简单函数的原型链时,一开始它似乎无穷无尽-但是后来我意识到,原型实际上是指自身。与Mozilla's documentation中提到的方式不同,此处的原型链似乎并没有以null
作为根。
我想这是为了支持基于原型的继承而设计的。但是,如果可以解释,我将不胜感激, 确切地说,原型构造函数中的这种自引用如何帮助实现这一目标 ?
答案 0 :(得分:3)
如果要查找此处描述的原型链:
每个对象都有一个私有属性,该属性持有指向另一个称为其原型的对象的链接。该原型对象具有自己的原型,依此类推,直到到达以null为原型的对象。根据定义,null没有原型,并充当该原型链中的最终链接。
您应该查看__proto__
属性(它将指向被检查对象的内部原型)。
在这里,您看到myFunctionObj
的内部原型为Function.prototype
,而上一个__proto__
的下一级将带您到Object.prototype
,后者没有{{ 1}}(原型链的末尾)。
__proto__
的{{1}}属性是指实例化对象的内部原型(例如prototype
,然后是myFunctionObj
),而不是const obj = new myFunctionObj();
本身的内部原型。
通常,只有obj.__proto__ === myFunctionObj.prototype
个具有myFunctionObj
属性,并且它们的function
将引用由.prototype
创建的实例的内部原型 。普通对象没有.prototype
属性(因为不能调用普通对象来实例化某些东西),但是您仍然可以使用new
访问普通对象(或任何对象)的内部原型。 (或.prototype
):
Object.getPrototypeOf
函数的.__proto__
实际上只是对函数的自引用。
const obj = {};
console.log(
obj.__proto__ === Object.prototype,
Object.getPrototypeOf(obj) === Object.prototype,
);
当您已经引用了构造函数时,它不是很有用,但是当您引用一个实例但不知道其构造器时,它 很有用-具有原型继承性,可以访问实例的.prototype.constructor
属性将为您提供用于构造它的函数:
function foo(){};
console.log(
foo.prototype.constructor === foo
);
答案 1 :(得分:0)
要回答第二个问题:
该原型对象具有自己的原型...
如果您实际看一下原型的多个级别及其在实践中的工作方式,那么理解这个概念会更容易:
function ClassA() {
this.a = 1;
}
ClassA.prototype.getA = function(){
return this.a;
};
function ClassB() {
this.b = 2
}
ClassB.prototype = new ClassA();
ClassB.prototype.getB = function(){
return this.b;
};
var b = new ClassB();
console.log(b.getA());
> 1
console.log(b.getB());
> 2
现在您会注意到,在定义类(函数)时,我们扩展(或添加)了prototype
。但是,当我们查看类的实例(在我的示例中为b
)时,没有prototype
;它被称为__proto__
,如@CertainPerformance所述)。因此,查看b
的原型链,您将看到:
b.__proto__
> ClassA {a: 1, getB: ƒ}
b.__proto__.__proto__
> {getA: ƒ, constructor: ƒ}
b.__proto__.__proto__.__proto__
> {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
b.__proto__.__proto__.__proto__.__proto__
> null
因此,当您键入b.getB()
时,JavaScript引擎首先查看b
对象中的直接属性,而看不到getB
。然后,它查看b.__proto__
并找到它,并完成了。
对于b.getA()
,它执行相同的操作,但在第一个原型中找不到。因此它继续到b.__proto__.__proto__
,并在那里找到它。
您看到的与众不同。首先,您要看一个函数的prototype
,并看到其中包含另一个名为constructor
的函数。并且由于constructor
也是一个函数,因此它内部有一个prototype
。等等,直到永远。但是那是构造函数的原型,不是是原始函数/对象的原型链的一部分。