
今天发现一张特别好的图(↑↑↑上图↑↑↑),对原型和原型链的理解特别直观友好。
原型和原型链
基础储备:
每个 JS 对象都有_proto_ 属性。这只是浏览器在早期为了让我们访问到内部属性 [[prototype]] 来实现的一个东西,这个属性在现在来说已经不推荐直接去使用它了。
原型是什么?
- 每一个对象都有一个内置的_proto_属性指向其构造函数的prototype对象
- prototype对象中含有constructor 属性指向构造函数本身
- 构造函数又通过 prototype 属性指回原型
- 注意并不是所有函数都具有这个属性Function.prototype.bind() 就没有这个属性
原型链是什么?
原型链顾名思义就是一条链,用代码解释如下:
var o = { name : "shf" };
console.dir(o);
console.dir(o.__proto__);
console.dir(o.__proto__.__proto__);
console.dir(o.__proto__.__proto__.__proto__);
上面代码定义了一个对象o,在未进行其他操作之前,o已经有几个属性(方法)了,比如:o.valueOf(),并且除了name属性还有还有一个_proto属性,逐级打印_proto属性最后会返回空,结合本文第一张图就能知道,当使用某个属性(方法)A时,引擎会这样做:
首先看o对象本身有没有A属性,有就返回,没有就沿着个_proto属性逐级向下查找,直到找到并返回,如果沿着_proto走到最后也没找到就会返回null;
这个过程通过_proto_将对象和原型连接起来,形成了原型链。
输出结果:

上面是定义了一个对象,定义一个构造函数也是这样的,只不过原型链长了一些。
function Person(){
this.name = "shf";
this.age = 28;
}
var p = new Person();
console.dir(p);
console.dir(p.__proto__);
console.dir(p.__proto__.__proto__);
console.dir(p.__proto__.__proto__.__proto__);
console.dir(p.__proto__.__proto__.__proto__.__proto__);
输出结果:

通过对象和构造函数的输出结果不难发现,当使用某个属性(方法)A时,引擎会首先查看本身有没有A属性,有就返回,没有就沿着个_proto_ 属性逐级向下查找,直到找到并返回,如果沿着_proto_ 走到最后也没找到就会返回null;这个过程通过_proto_ 连接起来,形成了原型链,就是本文最开始那张图。
网友评论