1 三个重要知识
1.1 JS公式
对象.__proto__ === 其构造函数.prototype
1.2 根公理
Object.prototype 是所有对象的(直接或间接)原型
1.3 函数公理
所有函数都是由 Function 构造的,任何函数.__proto__ === Function.prototype
2 原型
2.1 XXX 的原型
XXX的原型等价于 XXX.__proto__
2.2 直接原型和间接原型
-
[1,2,3]的原型是Array.prototype,而Object.prototype 是所有对象的原型,为什么 Object.prototype 不是[1,2,3] 的原型?
-
因为原型分为直接原型和间接原型,对于普通对象来说,Object.prototype 是直接原型,对于数组、函数来说,Object.prototype 是间接原型;
2.3 Object.prototype 是不是根对象
- 问:Object.prototype 是所有对象的原型,Object 是 Function 构造出来的,所以,Function 构造了 Object.prototype,推论:Function 才是根;
答:Object.prototype 存储的是 Object.prototype 对象的地址,Object.prototype 对象中包含对象的公有属性,两者是不同的,Function 并没有构造出 Object.prototype 对象,它只是构造了存储 Object.prototype 对象的地址的属性,这个属性包含了 Object.prototype 对象的地址。
- 对象里面从来都不会包含另一个对象,只会包含另一个对象的地址;
3 JS世界的构造顺序
- 创建根对象#101(有 toString、valueOf 等方法),根对象没有名字;
- 创建函数的原型#204(有 call、apply 等方法),原型 proto 为#101;
- 创建数组的原型#404(有 push、pop 等方法),原型 proto 为#101;
- 创建 Function #2111 ,原型__proto__为 #204,
- 用 Function.prototype 存储函数的原型,等于#204;
- 此时,Function 的__proto__ 和 prototype 都是#204 ,这是浏览器默认设置的;
- 用 Function 创建 Object;
- 用 Object.prototype 存储对象的原型,等于#101;
- 用 Function 创建 Array;
- 用 Array.prototype 存储数组的原型,等于#404;
- 创建 window 对象;
- 用 window 的 'Object'、'Array'属性将 7 和 9 中的函数命名为 window.Object、window.Array ,在此之前,对象都没有名字;
- JS 创建一个对象时,不会给这个对象名字;
- 根没有名字,window.Object.prototype 正好存了根的地址;
4 new
- 用 new Object() 创建 obj1 ;
- new 会将 obj1 的原型 proto 设置为 Object.prototype,也就是 #101;
- 用 new Array() 创建 arr1 ;
- new 会将 arr1 的原型 proto 设置为 Array.ptorotype,也就是 #404;
- 用 new Function 创建 f1; 6, new 会将 f1 的原型 proto 设置为 Function.prototype,也就是 #204;
5 构造函数
- 自己定义构造函数,例如:Person,函数里用 this 加属性,
this.name = name; - Person 自动创建 prototype 属性和对应的对象#502;
- 在 Person.prototype #502 上面加属性;
- 用 new Person() 创建对象 P;
- new 会将 P 的原型 proto 设为#502;
6 图示
7 总结
- 构造函数
- 是用来构造对象的;
- 会预先存好对象的原型,原型的原型是 根;
- new 的时候将对象的 __ proto__ 指向原型;
- 对象
- 所有对象都直接或间接指向根对象;
- 如果对象想要分类,就在原型链上加一环;
- 用构造对象可以加这一环;
- 如果加了一环以后,还想再加一环,需要用到继承;