这里先不考虑我们自己构造了原型,如果给我们一个值,我们如何有效迅速地判断与它相关的原型(原型链)呢?
其实并不难,只要我们死死抓住那一些最根本的规则:
规则一:
javaScript 八种基本数据类型中,除了 null 和 undefined,其它任何类型的数值都是从它相对应的构造函数继承了原型;
string → String
number → Number
规则二:
除了基本数据类型,其它所有的对象,都从 Object 构造函数继承原型;
规则三:
Object.prototype 的原型是 null;
规则四:
xxx.prototype 是个对象; Object / Array / Boolean / Function 是函数!
规则五:
"proto" 属性指向原型,“原型”是“构造函数的 prototype 属性”
值.__proto__ === 构造函数.prototype
于是,我们开始来绕吧:
let a = "string";
//(1)开始
a.__proto__ // → ?
// a 是 string, 所以它的原型继承于 String 的 constructor `String.constructor`
//(2)继续
a.__proto__.__proto__ // → ?
// 经过上一步分析,上面式子等于:
//(3)那么
String.constructor.__proto__ // → ?
// constructor(原型) 是个什么东西呢?就是一堆“共用的属性”,也就是一个对象,对象的 __proto__ 是 (规则二)…… Object.prototype.
//(4)那么
String.__proto__ // → ?
// String 是构造函数,函数的原型 …… Function.prototype;
//(5)继而
Function.prototype__proto__ // → ?
// 详见3
//(6)于是
Function.__proto__ // → ?
// 详见4
// 没看错
Function.__proto__ === Function.prototype //→ ture
//(7)还有
Object.__proto__ // → ?
//当然还是 Function.prototype
//(8)最终
Objecgt.prototype.__proto__ // → ?
// null, 规定
总结下来:
判断这些基本的原型,最重要的一步就是确定值的数据类型:
除了 Object.prototype.proto === null;
除了 null, undefined 没有原型;
其它的,不管它们多乱,我们只要看它们是哪一类基本数据类型,就知道它们从哪里继承。