构造函数和原型对象
构造函数也是一个函数。用新函数创建对象时调用的函数和普通函数的区别在于它的首字母应该大写。但是,如果构造函数是作为普通函数调用的(缺少new关键字),就要注意这个所指向的问题。
var name=' Pomyfunction Per(){ console . log(' Hello ' this . name);} var Per 1=new Per();//“Hello undefined”var Per 2=Per();//“Hello Pomy”自动创建此对象,该对象属于构造函数类型,指向对象实例;缺少新关键字,这指向一个全局对象。
Instanceof可用于检测Object类型,每个Object在创建时自动有一个构造函数属性,指向其构造函数(文字或对象构造函数创建的对象指向对象,自定义构造函数创建的对象指向其构造函数)。
console . log(Per 1 instance of Per);//true console . log(Per 1 . constructor===Per);//true每个对象实例都有一个内部属性:[[Prototype]],它指向对象的原型对象。构造函数本身也有指向原型对象的原型属性。所有创建的对象共享原型对象的属性和方法。
函数PeRsoN(){ } PeRsoN . prototype . name=' dwqs ';person . prototype . age=20;person . prototype . SayName=function(){ alert(this . name);};var per 1=new Person();per 1 . SayName();//dwqsvar per 2=new Person();per 2 . SayName();//dwqsalert(per 1 . SayNAmE==per 2 . SayNAmE);//真
因此,实例中的指针只指向原型,而不指向构造函数。ES5提供了hasOwnProperty()和isPropertyOf()方法来反映原型对象和实例之间的关系
alert(person . prototype . is rototypeof(per 2));//trueper 1 . blog=' www . ido 321.com ';alert(per 1 . hasown property(' blog '));//true alert(person . prototype . hasown property(' blog '));//false alert(per 1 . HasownProperty(' name '));//false alert(person . prototype . hasown property(' name '));//true由于原型对象的构造函数属性指向构造函数本身,所以在重写原型时需要注意构造函数属性的指向问题。
函数Hello(name){ this . name=name;}//重写原型hello . prototype={ sayhi : function(){ console . log(this . name);}};var hi=new Hello(' Pomy ');console . log(hi instance of Hello);//true console . log(hi . constructor===Hello);//false console . log(hi . constructor===Object);//true用对象的文字形式覆盖原型对象会改变构造函数的属性,因此构造函数指向对象而不是Hello。如果构造函数指向很重要,则需要在覆盖原型对象时手动重置其构造函数属性
hello . prototype={ constructor : hello,sayhi : function(){ console . log(this . name);}};console . log(hi . constructor===Hello);//true console . log(hi . constructor===Object);//false利用原型对象的特性,我们可以很容易地为JavaScript的内置原型对象添加自定义方法:
array . prototype . sum=function(){ return this . reduce(function(prev,cur){ return prev cur;});};var num=[1,2,3,4,5,6];var RES=num . sum();console . log(RES);//21 string . prototype . capit=function(){ return this . charat(0)。toUpperCase()this . substring(1);};var msg=' hello worldconsole . log(msg . capit());//《你好,世界》遗产
使用[[原型]]功能,可以实现原型继承。对于文字形式的对象,Object.prototype被隐式指定为它的[[prototype]],也可以由Object.create () display指定,它接受两个参数:第一个是[[Prototype]]指向的对象(Prototype对象),第二个是可选的属性描述符对象。
Var book={title: '这是书的标题';};//用下面同样的方法,varbook=object . create(object . prototype,{ title: {可配置: true,可枚举3360 true,value: '这是书的标题',wrappable 3360 true } });默认情况下,文字对象继承自对象。更有趣的用法是实现自定义对象之间的继承。
var book1={ title:'JS高级程序设计,gettitle : function(){ console。日志(这个。标题);}};var book2=Object.create(book1,{ title : {可配置: true,enumerable:true,value:'JS权威指南,wra表: true } });第一本书。gettitle();//'JS高级程序设计第二本书。gettitle();//'JS权威指南控制台。日志(第一册。hasown属性(' getTitle ');//真控制台。日志(第一册。is rototypeof(' book 2 ');//假控制台。日志(第二册。hasown属性(' getTitle ');//false当访问第二册的getTitle属性时,JavaScript引擎会执行一个搜索过程:现在第二册的自有属性中寻找,找到则使用,若没有找到,则搜索[[原型]],若没有找到,则继续搜索原型对象的[[原型]],直到继承链末端。末端通常是对象。原型,其[[原型]]被设置为零。
实现继承的另外一种方式是利用构造函数。每个函数都具有可写的原型属性,默认被自懂设置为继承自对象。原型,可以通过改写它来改变原型链。
函数Rect(长度,宽度){ this.length=lengththis.width=宽度;} rect。原型。GetArea=function(){返回这个。宽度*这个。长度;};Rect。原型。tostring=function(){ return '[Rect]this。长度' * '这个。宽度']';};函数正方形(大小){这个。长度=尺寸;this.width=size}//修改原型属性正方形。prototype=new Rect();方形。原型。构造函数=Square方形。原型。tostring=function(){ return '[Square ' this。长度' * '这个。宽度']';};var rect=new Rect(5,10);var Square=新的Square(6);控制台。日志。GetArea());//50控制台。原木(方形。GetArea());//36如果要访问父类的toString(),可以这样做:
正方形。原型。tostring=function(){ var text=rect。原型。tostring。叫(这个);返回文本。替换('矩形','方形');}