JavaScript面向对象这一块的底层原理是很难掌握的,基本是看了忘,忘了再看的循环过程。最近深入理解new
运算符底层原理的时候,又看了一遍关于面向对象这一块的知识点,从而有了新的认识。本篇只讨论基于原型模式创建对象,对涉及到的知识点只做简单补充,后续进行细化和整体的对比。
function Person() {
}
Person.prototype.name = "Nicholas"
Person.prototype.age = 29
Person.prototype.sayName = function() {
alert(this.name)
}
var person1 = new Person()
var person2 = new Person()
上面的这一段代码,是整个原型模式创建对象的过程,接下来对每段代码进行细化和图解。
function Person() {}
解释:
当我们在创建一个新函数的时候,JavaScript引擎就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性是一个指针,指向函数的原型对象。而这个原型对象的用途是包含可以由特定类型的所有实例共享的属性和方法。按照字面意思来理解, prototype 就是通过调用构造函数而创建的那个对象实例的原型对象。
上面的解释难理解的话,我们可以简单归纳下,就是在我们创建任意函数(在此指构造函数)的时候,浏览器会自动创建一个 prototype 属性指向一个对象,这个对象我们叫做原型对象。
图解:
关于上图中原型对象中的 constructor 的属性,可以这样理解。
在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数)属性,这个属性是一个指向 prototype 属性所在的函数的指针;从另一个方面理解,Object 的每个实例都拥有 constructor 属性,由于在 ECMAScript 中 Object 是所有对象的基础。那么原型对象Person.prototype 有一个 constructor 属性,保存着用于创建当前对象的函数。在此例中,Person.prototype.constructor 指向 Person。
通过浏览器控制台我们可以证明上面所说的,Person.prototype.constructor 指向 Person。
Person.prototype.name = "Nicholas"
Person.prototype.age = 29
Person.prototype.sayName = function() {
alert(this.name)
}
解释:
使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。换句话说,我们不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。
图解:
var person1 = new Person()
var person2 = new Person()
解释:
当调用构造函数创建一个新实例后,该实例的内部将包含一个指针_proto_(内部属性),指向构造函数的原型对象。需要强调的就是这个指针指向的构造函数的原型对象,而不是构造函数。
图解:
本文主要参考于红宝书《JavaScript高级程序设计》,像他们说的,这本书看多少遍都不为过,每次看都会有新的认识。一上午就才搞明白这里面的关系,看到给个赞哦!接下来会进一步搞明白在构造函数里面定义对象实例信息来创建对象和原型模式有什么区别和联系。