原型链之 __proto__ 和 prototype

原型链每隔一段时间就容易忘记,所以整理一下,便于回顾。

用下面的代码 demo 来帮助理解:

function Person(name, age, job) {
  this.name = name;
  this.age  = age;
  this.job = job;
  this.sayName = function() {
    console.log(this.name);
  }
}

let person1 = new Person('nick', 29, '程序员')
let person2 = new Person('tom', 28, '摄影师')

person1.sayName();    // nick
person2.sayName();    // tom

image

先看图,有个大体印象:
构造函数原型链 (4)

定义

prototype

  • 是个对象,并且有个 [[constructor]] 方法

  • 函数和类(es6)才有,箭头函数、普通对象都没有prototype,例如:

普通对象:__proto__
函数:__proto__、prototype
// 箭头函数没有
let a = () => {}
> a.prototype  
< undefined 

> a.__proto__
< ƒ () { [native code] } 

> a.__proto__.constructor
< ƒ Function() { [native code] }

es6 的 class 具有 prototype:
image

__proto__

这个属性是用来标识自己所继承的原型,用来读取或设置当前对象的prototype对象,他本质是一个内部属性,不是一个正式对外的api,由于浏览器的广泛支持,才加入了es6,__proto__调用的是Object.prototype.proto。

对象__proto__属性的值就是它所对应的原型对象。

image

结论:
1.所有对象都有__proto__属性。
2.只有函数对象才有prototype属性。
3.protoype对象默认有两个属性:constructor 和 proto
4.实例对象的__proto__指向的是函数的protoype
5.函数对象的prototype属性是外部共享的,而__proto__是隐式的。
6.函数和Object的__proto__的顶端是null

参考:
https://segmentfault.com/a/1190000011801127
https://juejin.cn/post/6844903790345191437