持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第32天,点击查看活动详情
1. 引言
来,介绍之前,咱们先上“祖”图
介绍原型链之前,我们先来了解一些必备知识项目
2. 定义
在JavaScript 编程语言中每个对象都有一个prototype属性,假如你在js中敲击设置一个空对象后,打印出来它,好好观察下
你会发现就是一个普通的空对象就像“洋葱”一样,其中包含了很多方法。可是明明我们没有预设任何属性方法啊?它们哪来的?其实这些都是JavaScript帮我们预设的,其中认真观察首先我们的第一层“洋葱皮”-- Object.Prototype 展开是一个Object对象;在展开第二层“洋葱皮”-- Proto 发现里面还有第三层;接着扒开第三层“洋葱皮” -- Proto 这时候返回的是null 。恭喜你,已经到最后一层了,成功抵达“洋葱芯”。
而上述这一个过程对于一个实例对象来说obj.proto.proto 就是我们常说的原型链,每个实例对象原型链的尽头都是null!!
3. 解析
- 什么是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就是构造函数实例的原型
- 什么是__prto__?
接着上述例子的代码,我们试下构造函数Person 的实例中都有什么
console.log(person1.__proto__ === Person.prototype) // true
console.log(person1.__proto__ === person1.constructor.prototype) // true
每个JavaScript对象(除了 null )都具有的一个属性,叫proto,这个属性会指向该对象的原型
大多数情况下,proto 可以理解为“构造器的原型”,即
__proto__ === constructor.prototype
- 什么是constructor? 每个原型都有一个 constructor 属性指向关联的构造函数 实例原型指向构造函数
console.log(Person.prototype.constructor === Person) // true
介绍完原型的三个相关知识点,我们来个小习题试试手
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
由上述例子可知,实例的原型prototype作为一个公共池的存在,但我们访问这个实例中的name属性时候,优先从实例本身寻找,当没有发现时候才会在person.proto 中寻找(也就是Person.prototype),假如protptype中也没有,它会通过__proto__原型链一层一层下探寻找,直到到原型链底层null为止,中间这个过程如果存在name,停止下探,直接回抛找到的结果。
下一节:请看
console.log(Object.prototype.__proto__ === null) // true
说明什么?说明实例都是对象,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
贴张“全图”