什么是构造函数?
构造函数本身就是一个函数,与普通函数没有任何区别,不过为了规范一般将其首字母大写。构造函数和普通函数的区别在于,构造函数用于使用new操作符生成实例,普通函数用来调用以实现某种功能。
什么是原型?
每个函数都有一个prototype属性,prototype属性中的constructor属性又指向函数自身。
什么是原型链?
引用高程3的描述:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型 对象的内部指针。那么,假如我们让原型对象等于另一个类型的实例,结果会怎么样呢?显然,此时的 原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数 的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实 例与原型的链条。这就是所谓原型链的基本概念。
如果你还没理解构造函数和原型的关系,看完对于上面这段话,很可能更加晕了,所以下面我将用我的理解来描述构造函数和实例之间的关系,以及原型链到底是什么。
function Person(name){ this.name = name; }; let xm = new Person('小明'); xm.__proto__ === Person.prototype // true xm.__proto__.constructor === Person // true Person.prototype.constructor === Person // true复制代码
Person为构造函数,xm是通过new Person()得到的实例,其对应关系如下图:
而如果我们这里的Person.prototype同时又是另一个foo构造函数的实例呢?
Person.prototype可以从foo.prototype继承属性和方法,xm又可以从Person.prototype继承属性和方法,由此得出以下结论:
每个对象都拥有一个原型对象,通过__proto__指针指向上一个原型 ,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层查找,最后指向Object.prototype,接着Object.prototype.__proto__ = null,对象之间的这种关系就是原型链。
那么如上代码的原型链关系图如下:
那如果加上Function对象又是什么样的呢?上图:
上图有一个让人疑惑的点就是为什么Function.__proto__ === Function.prototype?
我比较认同的一种观点是:Function作为一个内置对象,是运行前就存在的东西,所以不会存在说Function自己创建自己,而同Function一起被创建的还有Function.prototype和Object.prototype,并通过__proto__将两者联系起来,而为了和其他对象保持一致性,将Function.__proto__指向Function.prototype。
总结:
Object是所有对象的祖先,所有对象都可以通过__proto__找到Ojbect.prototype;
Function是所有函数的祖先,所有函数都可以通过__proto__找到Function.prototype;
每一个实例通过__proto__指向构造函数的原型,而构造函数的原型又通过__proto__指向构造函数的原型的原型,如此一层一层链接的关系,就是原型链。
如果有错误或者不严谨的地方,请给予指正,十分感谢!