我对JS中的原型、原型链的理解与总结

187 阅读3分钟

原型

JS原型和原型链是JS基础知识中的重中之重,我们一定要把这部分内容理解透彻。为了弄懂JS中的原型和原型链,我们要先弄清楚以下几点。

  • JS中的对象分为函数对象和普通对象,每个对象都有__proto__属性,但是只有函数对象才有prototype属性,也就是原型对象属性,原型对象属性声明了该函数对象的原型是谁,这也是原型链的一个具体应用。
  • Object, Function等等都是JS内置的函数,与之类似的还有Array, Date, Boolean, Number, String, RegExp等。
  • 属性__proto__也是一个对象,它有两个属性,一个是constructor构造函数,一个是__proto__,指向原型链的上一级。
  • 原型对象有默认的constructor属性,用于记录实例是由哪个构造函数创建的。

在原型这部分知识中,有两个准则需要牢记。

  1. 原型对象的constructor指向构造函数本身。
Book.prototype.constructor == Book
  1. 实例的__proto__和原型对象指向同一个地方
book1.__proto__ == Book.prototype

除了Object的原型对象的__proto__属性指向null,其他内置函数对象的原型对象和自定义构造函数的__proto__都指向Object.prototype。

Object.prototype.__proto__ = null
Array.prototype.__proto__ = Object.prototype

从上面的说明可以看出,原型对象的作用在于存储该函数对象或者说该“类”实例中共有的那些属性和方法,从而大大减少内存的消耗。原型对象和该函数对象(该类)密切绑定,不管是函数对象还是普通对象都可以使用__proto__原型属性来得到JS原型链的上一级对象。

原型链

我们一定要熟知,每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,也就是constructor属性;而实例都包含一个指向原型对象的内部指针,也就是__proto__属性。那么什么是原型链呢?别急,我们慢慢分析。

在JS中,如果我们调用对象的某个属性,会首先在对象内部寻找该属性,如果找不到会去对象原型中寻找。看下面这个例子,我们让constuctor1.prototype = instance2, 也就是让构造函数的原型对象指向另一个构造函数的实例。那么如果我们要引用构造函数1创建的实例instance1的某一个属性p1,这模拟的就是JS中的继承,按照上述原则:

  • JS会先在instance1实例内部属性中查找p1
  • 接着会去instance1.__proto__也就是constructor1.prototype中继续寻找p1,而constructor1.prototype已经被我们定义为instance2,所以JS会在instance2的内部属性中查找p1,同样JS也不会在这里找到p1属性。
  • 如果还是没有找到p1的话,JS会继续往instance2.__proto__也就是constructor2.prototype中查找,直到Object的原型对象。 这整个搜索过程,就是原型链,原型链使用到了__proto__属性作为连接桥梁。其实,原型链帮助我们实现了继承。下面引用掘金作者路易斯的一段代码,帮助我们理解一下原型链和继承的关系。
function Father(){
	this.property = true;
}
Father.prototype.getFatherValue = function(){
	return this.property;
}
function Son(){
	this.sonProperty = false;
}
// 继承 Father
Son.prototype = new Father(); 
// Son.prototype被重写,导致Son.prototype.constructor也一同被重写
Son.prototype.getSonVaule = function(){
	return this.sonProperty;
}
var instance = new Son();
alert(instance.getFatherValue());//true

作者:路易斯
链接:https://juejin.cn/post/6844903475021627400
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。