原型链,实例原型与实例对象
构造函数与实例原型
什么是构造函数?
构造函数与普通函数的区别:
1. 构造函数通常以大写字母开头命名,普通函数则常采用驼峰式命名或纯小写;
2. 调用方式不同:构造函数常用new关键字调用,普通函数直接调用函数名。
3. 意义不同:构造函数代表生成一个类,和关联一个原型实例,其类名就是它的函数名;普通函数只是调用函数并执行函数体。
4. 构造函数通过this来构造类的属性和方法。
new一个对象的过程中发生了什么?
- 创建一个新对象;
- 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
- 执行构造函数中的代码(为这个新对象添加属性);
- 返回新对象。
那么构造函数和原型对象,也就是实例原型的关系是什么?
每一个构造函数被创建后,都会与实例原型相关联,其关联方式就
是通过prototype指针,指向原型对象(实例原型)。
构造函数又称为对象构造器,而每个实例原型与构造器之间通过constructor进行关联,也就是说实例原型有一个指针指向构造函数,这个指针就是constructor。
举个栗子~
1 | function Person(){ |
实例对象
通过 new 关键词调用构造器函数可以创建相同类型的对象:这个对象就叫做实例对象,而构造器函数又可以称为这个对象的类。
通过instanceof可以判断这个对象是否继承自该类。
1 |
|
对于每一个对象,都会有一个内部指针,指向原型对象。该指针为proto
1 | person.__proto__===Person.prototype |
那么如果我找到person的构造器是谁,这时候应该怎么办?
这就是原型链的核心,通过原型链向上寻找一些属性。
person.constructor本来在person实例对象中是没有constructor的,但是其原型对象是有constructor属性,当我们在控制台输入person.constructor时,是可以获取到其构造器Person。
这个过程就是person到其原型对象,也就是通过proto向上寻找,看每个原型对象是否有该属性,如果有,则停止寻找并返回结果。
所以,实际上,就是通过person.proto.constructor找到的Person。
验证一下
1 | person.constructor===Person.prototype.constructor |
原型链
如果原型对象找不到,那么则去找原型对象的原型对象。
最上层的原型对象是谁呢?
答案是,Object。
因为实际上JavaScript中只有一种复杂结构,就是Object,所以所有对象都是位于原型链顶层Object的实例。
当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象( object )都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( proto ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
所以可以这么理解,Person的原型对象其实是Object原型对象的实例对象,所以通过内部指针proto可以访问到Object的原型对象,为什么说是Object的原型对象呢,因为Object本身是一个对象构造器。
1 | Person.prototype.__proto__==Object.prototype |