# javascript 原型及原型链

原型链这个词在js里面一直都是一个比较高级的词汇,每逢面试,面试官都会问你懂不懂原型链,来达到自己装逼的目的
但在笔者看来,原型链是一个比较基础的东西,我们知道越是基础的东西,其实是越难掌握的,越难真正的弄懂,需要你每隔一段时间反复的 理解、消化 ,然后变成自己的东西

# 重要概念

  • 每个函数都有prototype
function pro(){}
console.log(pro.prototype)

prototype

  • 每一个对象都有__proto__属性(这个属性称之为原型)如:
const obj = {}
console.log(obj.__proto__)

proto

  • 对象的_proto__ 指向他构造函数的prototype,如:
const obj = {}

const proto = obj.__proto__;
// 我们知道 `{}` 的构造函数是 `Object`
const protype = Object.prototype;
console.log(proto === protype) //true

  • 在举一个例子 可能上边的例子不太常用, 我们举个完整的
function Pre(){
    this.name:'码不停息';
    this.age = 18;
}
const pre= new Pre();

pro.__proto__ === Pre.prototype  //true

我们可以清楚的看到,pre是由Pre new(创建出来的) 且 pro.__proto__ === Pre.prototype

# 原型链

其实这种__proto__向上查找的过程就是一种链状,也就是原型链
其他pre.proto.proto 和Per.prototype.__proto__最后都指向了Object 这也就所谓的”万物皆对象” 都是由对象创建出来的

我们上一节说的 instanceof 就是沿着这条原型链查找的

所以说会出现 函数的instanceof 也是对象,就是因为都是Object 创建出来的

# new的时候干了什么

我们拿上面的 const pre = new Pre() 为例 执行new操作会分为一下几个步骤

  1. 创建了一个空对象 pre = {}
  2. 将空对象的_proto__ 指向Pre的prototype
  3. 将Pre内部的this指向替换为pre(这个时候pre就可以通过 . 语法访问到对应的值了)
  4. 返回这个新对象

以下是伪代码

1. const pre = {}
2. pre.__proto__ = Pre.prototype
3. Pre.call(this,pre)
4. return pre

# 检查

对象的 hasOwnProperty() 来检查对象自身中是否含有该属性 使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型链中有,也会返回 true

function P(){
    this.name = '码不停息'
} 
P.prototype.age = 18
const p = new p();

p.hasOwnProperty('name') // true
p.hasOwnProperty('age') //false

'name' in p //true
'age' in p //true

# 总结

我们要时刻记住一句话

TIP

每个函数都有prototype,每一个对象都有__proto__属性(这个属性称之为原型),在我们执行new的时候对象的_proto__ 指向这个构造函数的prototype

指向图:
指向图1 指向图2