一切都是根据这张图展开的思考,这是一个最基础的原型链构成
相应的代码很简单:
function Foo() {...};
let f1 = new Foo();
既然每两个相邻对象或函数之间的关系只可能有prototype、constructor、_ _ proto _ _ 三种,那么这三种联系能不能分别各自构成链式结构呢?
1. prototype
因为只有构造函数有prototype,prototype指向其原型对象就停了,所以prototype不能构成链式结构
2. constructor
除了null所有东西都有constructor,constructor指向构造函数,constructor链的终点是Function(),Function()自己的constructor就是他自己
实例f1 -> Foo() -> Function()
Foo.prototype -> Foo() -> Function()
Function.prototype -> Function()
Object.prototype -> Object() -> Function()
3. _ _ proto _ _
_ _ proto _ _ 构成的就是传说中的原型链,在本例中原型链可以分为实例的原型链以及构造函数的原型链:
实例f1 -> Foo.prototype -> Object.prototype -> null
所有构造函数 -> Function.prototype -> Object.prototype -> null
之前一直对原型对象没有一个直接的理解,所以试着控制台输出了一下,下图是Foo.prototype,可以看出Foo的原型对象其实也就是一个仅包含constructor和[[Prototype]]两个隐藏属性的普通对象罢了,完全没有那么神秘嘛!
再来看看下图的Object.prototype,发现Object的原型对象甚至只有一个constructor属性,并且这个constructor就是Object自己。Object的原型对象没有再往上的[[Prototype]]了,这就是原型链的终点。
还有一个小疑惑: 同样是查询Object的原型对象中不存在的属性,为什么__proto__是null,而其他其他的普通字段会返回undefined呢?
我目前的理解:undefined是被动生成的空,null是主动赋值的空
难度进阶
如果两个类间有继承关系,那么原型链又会长什么样呢?上图: