JS中的原型链(超清晰理解)

什么是原型链

原型链,所有的原型构成了一个链条,这个链条我们称之为原型链(prototype chain)。

原型链的案例

如果我们执行下面这段代码,因为没有定义address这个属性,程序结果理所当然的是undefined。

let obj = {
    name : 'harry',
    age:18
}

console.log(obj.address);  //undefined

这个时候经历了什么呢?JS引擎线从Obj.address里寻找,发现没有找到,然后接着去找obj.__ proto __ 里面寻找,发现还是没找到,所以结果为undefined。我们可以给obj.__ proto __ 赋值

let obj = {
    name : 'harry',
    age:18
}
obj.__proto__ = {
    address:'上海'
}
console.log(obj.address); //上海

或者这样

obj.__proto__ = {
    //这里一定要开辟一个空间,不能直接写obj.__proto__.__proto__ = {}
}
obj.__proto__.__proto__= {
    address:'上海'
}
console.log(obj.address); //上海

接着套娃

let obj = {
    name : 'harry',
    age:18
}

obj.__proto__ = {

}
obj.__proto__.__proto__= {
    
}
obj.__proto__.__proto__.__proto__= {
    address:'上海'
}
console.log(obj.address); //上海

js引擎会顺着这些原型不断的往上找,直到address这个属性。这些原型构成了原型链。

原型链的顶层

那如果我们一直找,哪里是头呢?先看一段代码。

let obj = {
    name : 'harry',
    age:18
}

console.log(obj.__proto__); //[Object: null prototype] {}顶层原型
console.log(obj.__proto__.__proto__) //null

这里的Object就是顶层原型,如果再往上找,结果就是null了(已经到了末尾,这个链表指向为null)。

Object是从哪来的

创建对象有如下的两种用法,Object也就来自于这里

var obj1 = {}  //创建了一个对象
var obj2 = new Object() //创建了一个对象,针对object也有new这个过程
针对object也有new这个过程

针对object也有new这个过程,这里怎么理解呢?在我之前写的两篇文章里都有介绍过,这里我再解释一下,如果没看过我之前两篇文章的朋友,可以访问JS批量创建对象的方案与构造函数JS中对象的原型与函数的原型 进行阅读。

此处new操作符经历的过程
  1. 现在内存中创建一个对象 let moni = {}
  2. this指向这个对象,也就是this = moni
  3. 将函数的显示原型prototype赋值给前面创建出来的对象的隐式原型,这里也就是obj2.__ proto __ = Object.prototype
  4. 如果构造函数没有对象,则返回空值。反之返回创建出来的新对象(moni)。这里也就是return this。

验证一下

console.log(obj2.__proto__ === Object.prototype)

并且大家要知道Object是所有对象的父类,(它是最顶层的原型)

研究一下Object.prototype里有什么
let obj1 = new Object()
console.log(Object.getOwnPropertyDescriptors(Object.prototype));

打印出来我们会发现,有非常多的值。

{
  constructor: {
    value: [Function: Object],
    writable: true,
    enumerable: false,
    configurable: true
  },
  __defineGetter__: {
    value: [Function: __defineGetter__],
    writable: true,
    enumerable: false,
    configurable: true
  },
  __defineSetter__: {
    value: [Function: __defineSetter__],
    writable: true,
    enumerable: false,
    configurable: true
  },
  hasOwnProperty: {
    value: [Function: hasOwnProperty],
    writable: true,
    enumerable: false,
    configurable: true
  },
  __lookupGetter__: {
    value: [Function: __lookupGetter__],
    writable: true,
    enumerable: false,
    configurable: true
  },
  __lookupSetter__: {
    value: [Function: __lookupSetter__],
    writable: true,
    enumerable: false,
    configurable: true
  },
  isPrototypeOf: {
    value: [Function: isPrototypeOf],
    writable: true,
    enumerable: false,
    configurable: true
  },
  propertyIsEnumerable: {
    value: [Function: propertyIsEnumerable],
    writable: true,
    enumerable: false,
    configurable: true
  },
  toString: {
    value: [Function: toString],
    writable: true,
    enumerable: false,
    configurable: true
  },
  valueOf: {
    value: [Function: valueOf],
    writable: true,
    enumerable: false,
    configurable: true
  },
  ['__proto__']: {
    get: [Function: get __proto__],
    set: [Function: set __proto__],
    enumerable: false,
    configurable: true
  },
  toLocaleString: {
    value: [Function: toLocaleString],
    writable: true,
    enumerable: false,
    configurable: true
  }
}

重点关注一下,打印的这么多值里也有constructor,在我的上一篇文章已经分析过了,这里constructor指向的就是构造函数本身,此处也就是Object。

来自本人掘金内容 https://juejin.cn/post/7111332278805987364/