关于自己对原型链的理解
参考网址:https://www.jianshu.com/p/08c07a953fa0
https://www.cnblogs.com/loveyaxin/p/11151586.html
说起原型链,就是在几个东西中转来转去(prototype, __ proto__,constructor),当时不理解这种复杂的链式结构,经过自己的学习,总算是有了初步的认识。
一、原型链
每个对象都可以有一个原型 __ proto__,这个原型还可以有它自己的原型,以此类推,形成一个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找...... 这个操作被委托在整个原型链上,这个就是我们说的原型链了。
二、原型指针
1. __ proto__
__ proto__ 是原型链查询中实际用到的,它总是指向 prototype,换句话说就是指向构造函数的原型对象,每个对象都可以有一个原型 __ proto__。
function Person() {
}
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true
2. prototype
在JavaScript中,每个函数都有一个prototype属性,这个属性指向函数的原型对象,这个属性是函数独有的。
function Person(age) {
this.age = age
}
Person.prototype.name = 'kavin'
var person1 = new Person()
var person2 = new Person()
console.log(person1.name) //kavin
console.log(person2.name) //kavin
例子中,函数的prototype指向了一个对象,而这个对象正是调用构造函数时创建的实例的原型,也就是person1和person2的原型。
原型的概念:每一个javascript对象(除null外)创建的时候,就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型中“继承”属性。
3. constructor
每个原型都有一个constructor属性,指向该关联的构造函数。
function Person() {
}
console.log(Person===Person.prototype.constructor) //true
补充说明:
function Person() {
}
var person = new Person();
console.log(person.constructor === Person); // true
当获取 person.constructor 时,其实 person 中并没有 constructor 属性,当不能读取到constructor 属性时,会从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性,所以:
person.constructor === Person.prototype.constructor
三、实例与原型
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。
function Person() {
}
Person.prototype.name = 'Kevin';
var person = new Person();
person.name = 'Daisy';
console.log(person.name) // Daisy
delete person.name;
console.log(person.name) // Kevin
在这个例子中,我们给实例对象 person 添加了 name 属性,当我们打印 person.name 的时候,结果自然为 Daisy。
但是当我们删除了 person 的 name 属性时,读取 person.name,从 person 对象中找不到 name 属性就会从 person 的原型也就是 person.proto ,也就是 Person.prototype中查找,幸运的是我们找到了 name 属性,结果为 Kevin。
但是万一还没有找到呢?原型的原型又是什么呢?
四、原型的原型
一张图概括就是
于是我们就可以得出:在原型链中的指向是,函数 → 构造行数 → Function.prototype → Object.protype → null 。