理解 JavaScript 中的 prototype、__proto__、construstor

968 阅读2分钟

一、需要记住的两个要点

  • constructor__proto__属性是对象所独有。

  • prototype 属性是函数所独有。但是,由于在 JS 中,函数也是一种对象,所以,函数也拥有__proto__constructor 属性。因此,函数拥有__proto__prototypeconstrustor 三种属性

image.png

二、 prototype 属性和 __proto__属性

  • prototype 属性是函数所独有的,它从一个函数指向一个对象,它的作用主要是让函数实例化的对象们都可以找到公有的属性和方法。 image.png
  • __proto__属性存在于对象中,它从一个对象指向另一个对象,即指向它的原型对象。需要注意的是,对象的__proto__只是存储了指向原型对象的地址,并不是原型对象。同时,根对象[Object.prototype]的__proto__属性指向的原型对象为空。 image.png
代码示例:
Object.prototype.__proto__ === null  // true
  • __proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象里找,如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象里找,如果还没找到,则继续往上找,直到原型链顶端null,再往上找就相当于在 null 上取值,会报错。以上这种通过__proto__属性来连接对象直到null的一条链即为我们所谓的原型链,而我们平时调用的字符串方法、数组方法、对象方法、函数方法等都是靠__proto__继承而来。另外,__proto__属性在 ES 标准定义中的名字应该是[[Prototype]],具体实现是由浏览器代理自己实现,谷歌浏览器的实现就是将[[Prototype]]命名为__proto__image.png

三、constructor 属性

  • constructor 属性也是对象才拥有的,它是从一个对象指向一个函数。
  • 每个对象都有构造函数,不是本身拥有就是继承而来,而所有函数最终的构造函数都指向 Function
  • 所有对象都会从它的原型上继承一个 constructor 属性,而所有 constructor 属性一出生就保存了对应的函数的地址
代码示例:
var o = {};
o.constructor === Object; // true

var o = new Object;
o.constructor === Object; // true

var a = [];
a.constructor === Array; // true

var a = new Array;
a.constructor === Array // true

var n = new Number(3);
n.constructor === Number; // true

四、公式1:函数创建的对象. __ proto__ === 该函数.prototype。

代码示例:
let obj = {};
obj.__proto__ === Object.prototype; // true

image.png

五、公式2:对象.constructor === 对象所在的构造函数

代码示例1Object.prototype.constructor === Object   // true

代码示例2function Tree(name) {
   this.name = name;
}
var theTree = new Tree("Redwood");
console.log( "theTree.constructor is " + theTree.constructor );   
// output
theTree.constructor is function Tree(name) {
this.name = name;
}

image.png

参考链接

帮你彻底搞懂JS中的prototype、__proto__与constructor(图解),by 码飞