1.什么是原型
(1)首先要明白一点:原型存在于对象中的。
接下来阐述什么原型:在js中,每个构造函数内部都有一个prototype属性,该属性的值是个对象,该对象包含了该构造函数所有实例共享的属性和方法。当我们通过构造函数创建对象的时候,在这个对象中有一个指针,这个指针指向构造函数的prototype的值,我们将这个指向prototype的指针称为原型。或者用另一种简单却难理解的说法是:js中的对象都有一个特殊的[[Prototype]]内置属性,其实这就是原型。
(2)理解原型:每个构造函数Object都有一个指针(prototype)指向原型对象(Object.prototype),
每一个原型对象都一个指针(constructor)指向构造者
构造函数创建的实例都有一个指针(__proto__)指向原型对象
构造函数 new Object() new Array() Array.prototype
原型对象都有一个指针指向一个构造者
看下例子
console.log(Object.prototype.constructor === Object);//true
var obj = {
name: 'zhangsan'
};
console.log(obj.__proto__ === Object.prototype);//true
console.log(obj.__proto__.toString());
console.log(obj.__proto__.valueOf());
// 实例调用的方法就是从原型对象中继承来
console.log(obj.toString() === Object.prototype.toString())
console.log(obj.hasOwnProperty() === Object.prototype.hasOwnProperty());
看图理解:
2.什么是原型链
先看下例子
function Animal() {
this.legNum = 4
}
Animal.prototype.run = function () {
console.log('prototype, i am running')
}
//这里只是为了方便,实际上并不推荐将属性值挂载到原型上
//因为存在喜闻乐见的引用类型问题
Animal.prototype.color = 'yellow'
const a1 = new Animal()
console.log(a1.color) //yellow
在Animal()构造函数中只定义了legNum,但是我们却通过a1这个实例取获取color,而且结果还获取到了。这是为什么?js中获取对象的属性时,第一步会先检查对象本身是否有该属性,如果有就直接使用。但是如果没有的话,就会到对象的原型上去找。
综合例子分析:a1实例上没有color属性,所以找向a1的原型,a1的原型包含一个run方法和一个color属性,所以找到,返回原型上color的值。如果还是没有的话,就会找a1原型对象的原型,层层向上找,原型链的尽头一般来说都是 Object.prototype ,所以这就是为什么新建的对象能够使用 toString() 等方法的原因。
所以原型链就是通过原型组成的一条查找链
注意:我们在开发的时候,要注意不要通过实例对象
去改变其构造函数
的原型对象
,这样会对其他通过该构造函数
生成的实例对象
造成影响。