请讲一下你对原型链的理解?
原型链
1. 实例和构造函数的关系
- 每个函数都有一个prototype属性,该属性指向由该函数创建的实例对象的原型
- 每个对象都有一个__proto__属性,该属性指向该对象的原型
- 因此,构造函数与由它创建的实例对象的关系为:
function Person() {}
const person = new Person()
console.log(Person.prototype === person.__proto__) // true
- 由此,构造函数和对象都可访问实例对象原型,原型是否可以访问构造函数和实例对象呢?
- 原型无法访问实例对象(毕竟一个构造函数可以生成多个实例对象,1对多情况下无法知道是哪个实例对象)
- 原型可以访问构造函数 ---- 通过constructor属性
console.log(Person.prototype.constructor === Person) // true
console.log(person.__proto__.constructor === Person) // true
2. 实例与原型的应用
- 读取一个对象的属性会沿着原型链查找,直到找到返回。
function Person() {}
Person.prototype.name = '小米'
var person = new Person()
person.name = '华为'
console.log(person.name) // 华为
delete person.name;
console.log(person.name) // 小米
// 先找 person.name 无再找person.__proto__.name 无再找 person.__proto__.__proto__.name...
3. 原型的原型
- 普通对象的原型的原型是null
const obj = new Object()
console.log(Object.prototype, Object.prototype.__proto__) // null
console.log(obj.__proto__.__proto__) // null
4. 面试题解答
请讲一下你对原型链的理解?
答: 由于对象与对象之间是存在联系的,而js就是通过原型链来建立这种联系。首先,对象可以通过构造函数来创建,构造函数有一个prototype属性,该属性指向的是便是原型,但它不是该构造函数本身的原型,而是该构造函数创建的实例对象的原型。而通过构造函数new出来的实例对象有一个__proto__属性,该属性便指向它的原型,也就是说构造函数的prototype是等于通过该构造函数创建的实例对象的__proto__。当一个对象访问一个属性时,他会先在该对象本身查找,若没有找到,则会沿着原型链查找,也就是说,会到原型上找,在找不到就去原型的原型上找,直到找到或找到最后一层,有则返回该属性的值,没有就返回undefined。此外原型是可以通过constructor属性来访问其构造函数的。
5. 面试题延伸
请问创建对象有哪几种方式?
既然原型链有继承或者说代理访问的特性,那如何知道一个属性属于它本身还是在它的原型上,能不能确定在哪个原型上?
js如何实现继承?