原型链
1.JavaScript中万物皆对象,JavaScript是基于原型的语言。
=> JavaScript 中万物皆为对象,对象皆有原型。
【几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。】
2. 构造函数升级具体化
ES5时期
- 普通函数: function function () {}
但是支持 let cupcustom = new function(); 普通函数能new调用
- 构造函数: function CupCustom (diameter, height) { // 制作杯子的模具
this.diameter = diameter; // 可传入不同直径
this.height = height; // 可传入不同高度
}
构造函数一般函数名首字母大写;
但是也支持CupCustom(10, 15); // 构造函数同样也能普通调用
let cup12 = new CupCustom(10, 15);
① 构造函数就是普通函数。函数都支持new调用和普通调用。
② cupcustom <=> CupCustom , Function <=> function。
ES6 推出 Class 类: 只支持 new 调用。
Class Parent {
addNumber () { console.log('加1'); }
}
1) let child1 = new Parent(); // 只支持 new 调用。
child.addNumber(); // 加1;
2) let child2 = Parent(); // 普通调用不支持!!!会报错!!!
构造函数属性继承理解:
构造函数相当于杯子模具;
let cup1 = new CupCustom(10, 15);
let cup2 = new CupCustom(8, 9);
cup1、cup2 为用模具 new 出来的杯子。
=>【杯子即实例】;
=>【即杯子继承了模具的直径和高度】。
=>【实例 可以继承 构造函数的构造器属性(直径和高度)】
CupCustom.prototype.color = 'blue';
=>【实例 可以继承构造器属性 又可以 继承原型属性(颜色)】
注意: 颜色属性存放在'__proto__'上面。
=> 【所有的对象都有__proto__属性,但只有函数拥有 prototype 属性。】
(js类型中仅 null 和 undefined 没有 __proto__属性)
=> 【构造函数有:自身属性 + __proto__属性 + prototype属性(仅构造函数本身有)】
__proto__:
- 是访问器属性;
- 是实例的属性,指向 创造它的 构造函数的prototype。
- 所以,杯子通过 __proto__的指向 找到了模具的prototype,
从而访问prototype上的原型属性color。
- 即:【实例通过__proto__指向 访问到了构造函数的prototype上的所有原型属性。】
③ 因为CupCustom模具本身是构造函数所以有prototype, 同时它也是由构造函数Function
new出来的实例所以CupCustom的__proto__指向构造函数Function的原型。
④【每一个函数都属于原始构造函数Function的实例,而每一个函数又能做为构造函数生产属于自己的实例】
⑤ let F = new Function;
F.__proto__ = Function.prototype;
Function.prototype.constructor = Function;
// prototype下constructor指向当前本身构造函数
【F.__proto__ 通过指向Function的prototype找到constructor。】
注释:很多人说实例的`constructor`指向创建自己的构造函数,但通过打印我们可以发现,
实例自己并没有`constructor`属性,而是通过`__proto__`属性,找到了构造函数的原型,
而构造函数的原型中有一个`constructor`属性指向自己。
原型链:
let F = new Function;
首先查找F自身是否具有某一属性,没有,就顺着F的__proto__往上查找创建F的构造函数
的原型上是否具有,没有,就沿着F的构造函数的原型对象的__proto__指向的构造
函数Object()的原型上找,还没有,就返回undefined。因为在往上就是null.
实例fn:{__proto__: ..., ...}
构造函数Fn:{prototype: {
constructor: 该构造函数本身
__proto__: {
constructor: Object(),
// 这里的constructor继承了 Fn的构造函数 的prototype下的constructor
// Fn的构造函数 的prototype被__proto__继承而来,指向Fn的构造函数Object()
// console.log(Object.prototype.__proto__) 为null
...
},
...},
...}
总结:
1) null<-- 构造函数Object()<-- 构造函数Fn()<--构造函数Fn-1()...构造函数F1()
原型链顶端.....................__proto__............................实例
2) 未修改prototype时:
Fn.prototype.constructor指向自身构造函数,值为Fn
Fn.prototype.__proto__.constructor指向Fn的构造函数
3) 每个函数function都有一个`prototype`,即显式原型(属性);
4) 每个实例对象都有一个 `__proto__`,即隐式原型(属性 )
注: [[prototype]],双中括号中的属性是系统的内置属性。
参考文档: