一直对JavaScript的原型与继承不了解,参考《JavaScript权威指南(第六版)》和《JavaScript高级程序设计(第三版)》对这个点的知识做个整理,方便自己记忆。以下内容大部分摘录自这两本书
每一个JavaScript对象都有与之相关的原型对象(prototype)。
原型对象有什么用?
JavaScript对象会继承原型对象的属性。
原型对象是从哪里来的?
首先我们先了解下创建对象基本的方式:
//1,对象直接量 var a={},b={m:1} //2,构造函数 var c=new Object(),d=new Date(); //3,Object.create(param); var x=Object.create(d);
1.使用对象直接量创建的对象使用Object.prototype作为它们的原型对象;
2.通过new创建的对象以构造函数的prototype属性作为原型对象;
3.通过Object.create()创建的对象使用第一个参数作为它们的原型对象;
说明:任何函数都可以是构造函数,比如有一个函数F,当使用 var f=new F()创建对象时,F就是对象f的构造函数;其他情况下F就是一个普通的函数
除了通过Object.create()创建的对象的原型是我们自己指定的外,Object.prototype和构造函数的prototype属性又是怎么来的呢?
1.Object.prototype是JavaScript内置的原型对象,定义了toString,valueOf等方法及一些属性。当我们通过var a={}创建对象a,虽然我们没有为a定义toString方法,但是当我们调用a.toString()的时候会返回"[object Object]",这是因为这个方法已经在Object.prototype定义了。
2.当我们创建函数的时候,JavaScript就会为该函数创建一个prototype属性。请看代码:
function F(){} console.info(F.prototype);//{constructor: ƒ} console.info(F.prototype.constructor===F);//true
原型链是什么?
先了解一下JavaScript对象原型的例外,在JavaScript中有少数对象是没有原型对象的。
1.Object.prototype
2.null
3.通过Object.create(null)创建的对象;
除上述对象外,所有的JavaScript对象默认都有一个原型对象。原型对象也是一个对象实例,如果它不属于上述3类对象,那么它也有自己的原型对象。比如a的原型对象是b,b的原型对象是c,c的原型对象是d……直到遇到上述3类没有原型对象的对象,从而在a,b,c,d……之间构成了一个链,a-->b-->c-->d……,这就是原型链。
原型链有什么用?
当在a中寻找一个属性,如果有返回属性值;如果没有就去b中找,有就返回属性值;如果没有就去c中找……,如果找到链的末端,还没找到就返回undefined。即通过原型链,实现了对象对原型链上的对象的继承。
说明:处在原型链前端的属性会隐藏后面对象的同名属性。比如:查找属性x,b和c中都有属性x,a.x的值等于b.x,而c中的x被隐藏了。
扩展原型链
构造函数有默认的原型对象,这个原型对象的原型对象是Object.prototype。那么,通过new加构造函数创建对象,原型链上只会有三个对象,如何扩展这个原型链呢?请看代码:
//本段代码来自于《JavaScript高级程序设计(第三版)》163页
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了 SuperType SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){ return this.subproperty; }; var instance = new SubType(); alert(instance.getSuperValue()); //true
红色代码处,我们修改了SubType函数的prototype属性的指向,使它指向了SuperType的一个对象实例。这个当我们通过new SubType()创建对象instance时,instance的原型对象是SuperType实例,而SuperType实例的原型对象是SuperType.prototype,SuperType.prototype的原型对象是Object.prototype。这样我们就扩展了对象instance的原型链。进而,我们也可以把SuperType.prototype设置为别的对象实例而再次扩展原型链。以此类推,我们可以无限扩展原型链。
可以看到通过原型链,可以在JavaScript中实现简单的继承:对象会继承自己原型链上的对象的属性。关于继承更进一步的知识请看《JavaScript高级程序设计(第三版)》6.3继承一节,讲的很详细。
以上就是对JavaScript原型最简单的总结。请各路大侠批评指正!