原型
每一个函数在创建时,都会被赋予一个prototype属性,它指向函数的原型对象,这个原型对象,可以包含所有由这个函数创建的所有实例共享的属性和函数。
这样就解决了,通过构造函数创建实例时,在不同的实例中重复创建的问题。
构造函数、原型对象、实例之间的关系
在一个函数创建时,都会被赋予一个prototype属性。
默认情况下,所有的原型对象都会增加一个constructor属性,指向prototype这个函数。
实例有一个__proto__属性,指向构造函数的原型对象,
实例与构造函数的原型对象有直接的联系,但实例与构造函数没有直接的联系。
实例属性的读取顺序
当我们读取实例的属性时,是一个搜索的过程。
它会在实例本身中找这个属性
- 如果找到了,就返回
- 如果没找到,沿着这个实例的原型对象寻找,在原型对象中找到了,就返回该属性
原型有什么用
获得一个属性的value时,优先在自己的对象中查找,如果找不到,就去原型对象中查找
一个构造函数,是有两部分组成的。
一部分是它的属性,在创建实例的时候,属性是定制化的,每个对象可能有自己独特的属性
一部分是它的函数,函数完成一定的功能,具有通用性
如果把函数直接写在函数内部,,每new一个对象,构造函数里面的函数对象就会都被创建一次。这样是很费内存的
如果把函数这样的通用信息保存在函数的原型中,就不会产生这样的问题了
如何获取原型
Object.getPrototypeOf
原型链
构造函数、原型对象、实例之间存在这样的关系:每个构造函数有一个原型对象,原型对象有一个属性指回构造函数,而实例有一个内部指针指向原型对象。
如果原型对象是另一个类型的实例,意味着原型对象有一个内部指针指向另一个原型,相应的,这另一个原型内部也有一个指针指向另一个构造函数。这样,实例和原型对象之间就构造了一条原型链(由__proto__属性连接而成的链路构成了原型链)。
每个原型对象有自己的__proto__属性,这个属性指向某一个原型对象,就这样形成了一条原型链
原型链相关知识
- 由于原型链的存在,属性查找会是沿着整个原型链的进行查找,如果查找路径过长,对性能影响大
- 对象的属性查找会沿着整个原型链,那么,对象的属性就可以分为两种:实例自身属性、原型链继承的属性。
hasOwnProperty()函数,在属性为自身属性时return true,在属性为原型链继承属性时return false - JavaScript中内置构造函数,如String()、Number()、Date()等,他们的__proto__都指向Function.prototype
原型链的终点
由上图可见,原型链的终点是Object原型对象的__proto__属性,指向null