可怕的链式反应--原型链解析

138 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第32天,点击查看活动详情

1. 引言

来,介绍之前,咱们先上“祖”图

图片.png

介绍原型链之前,我们先来了解一些必备知识项目

2. 定义

在JavaScript 编程语言中每个对象都有一个prototype属性,假如你在js中敲击设置一个空对象后,打印出来它,好好观察下

图片.png

你会发现就是一个普通的空对象就像“洋葱”一样,其中包含了很多方法。可是明明我们没有预设任何属性方法啊?它们哪来的?其实这些都是JavaScript帮我们预设的,其中认真观察首先我们的第一层“洋葱皮”-- Object.Prototype 展开是一个Object对象;在展开第二层“洋葱皮”-- Proto 发现里面还有第三层;接着扒开第三层“洋葱皮” -- Proto 这时候返回的是null 。恭喜你,已经到最后一层了,成功抵达“洋葱芯”。

而上述这一个过程对于一个实例对象来说obj.proto.proto 就是我们常说的原型链,每个实例对象原型链的尽头都是null!!

3. 解析

  1. 什么是prototype? 在每个构造函数上才有个prototype 属性(null除外),在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。可以理解为prototype 就是一个“公共池”,存放所有公共的属性和方法。Person.prototype 指的就是对象的原型
function Person() {

}

Person.prototype.name = 'guozi';
var person1 = new Person();
var person2 = new Person();
// 注意:person1和person2 是独立的,只有访问它们的prototype.name 这个公共属性的时候才是一致的
console.log(person1.name) // guozi
console.log(person2.name) // guozi

console.log(person1.name === person2.name) // true
console.log(person1 === person2) // false

结论:Person.prototype就是构造函数实例的原型

图片.png

  1. 什么是__prto__? 接着上述例子的代码,我们试下构造函数Person 的实例中都有什么 图片.png
console.log(person1.__proto__ === Person.prototype) // true
console.log(person1.__proto__ === person1.constructor.prototype) // true

每个JavaScript对象(除了 null )都具有的一个属性,叫proto,这个属性会指向该对象的原型 大多数情况下,proto 可以理解为“构造器的原型”,即 __proto__ === constructor.prototype

图片.png

  1. 什么是constructor? 每个原型都有一个 constructor 属性指向关联的构造函数 实例原型指向构造函数
console.log(Person.prototype.constructor === Person) // true

图片.png

介绍完原型的三个相关知识点,我们来个小习题试试手

function Person() {
  name: 'guozi'

}

Person.prototype.name = 'guozi,haha';

var person = new Person();

person.name = 'guozi,say haha';
console.log(person.name) // guozi,say haha

delete person.name;
console.log(person.name) // guozi,haha
person.name = 'zhansan'
console.log(person.name) // zhansan

图片.png

由上述例子可知,实例的原型prototype作为一个公共池的存在,但我们访问这个实例中的name属性时候,优先从实例本身寻找,当没有发现时候才会在person.proto 中寻找(也就是Person.prototype),假如protptype中也没有,它会通过__proto__原型链一层一层下探寻找,直到到原型链底层null为止,中间这个过程如果存在name,停止下探,直接回抛找到的结果。

图片.png

下一节:请看

console.log(Object.prototype.__proto__ === null) // true 图片.png

说明什么?说明实例都是对象,js 中万物皆对象,对象的尽头就是 null啊,++朋友们,划重点++

4. 印证

//图中的一些关系  
person.__proto__ === Person.prototype  
  
Person.prototype.__proto__ === Object.prototype 
  
person.__proto__.__proto__ === Object.prototype  
  
Person.prototype.constructor === Person   
  
Person.prototype.isPrototypeOf(person)  
  
//获取对象的原型  
person.__proto__  //不推荐  
Object.getPrototypeOf(person) === Person.prototype   //推荐  

5. 结论

每个对象都有一个__proto__,它指向它的prototype原型对象,而prototype原型对象又具有一个自己的prototype原型对象,就这样层层往上直到一个对象的原型prototype为null

贴张“全图” 图片.png