面向对象的JavaScrpt综合分析
每次说到面向对象的javascript,总觉得心里有数,但不知道怎么说,意思是懂不懂。结果每次谈起来都要到处找资料,零零碎碎的看完就觉得懂了,但是过了一段时间好像就不知道怎么回事了。结果我到处找资料,但办法是我已经缺对象了。我不懂什么是对象,所以在现实中找对象,在javascript中找对象!哦,多尴尬啊!直到看到一篇姊妹论文写了“必须知道的javascript面向对象”,我才明白什么是面向对象。这是不是意味着我要找的对象就是这张姐妹纸?让我们先记录备忘录。以下是姊妹论文的主要内容:
对象的创建:
1创建一个面向对象的
var obj=新对象();obj.name='哈哈';obj . show name=function(){ alert(obj . name);} obj . show name();缺点:当我们想要创建多个面向对象时,重复代码太多,需要封装,所以我们有工厂方法。
2工厂模式
函数CreatePerson(name){ var obj=new Object();//原材料obj.name=name//正在处理obj . show name=function(){ alert(this . name);}返回obj//factory }var p1=CreatePerson('哈哈');P1 . show name();var p2=CreatePerson('呵呵');p2 . show name();//其实就是一个简单的封装功能,整个过程就像工厂流水线一样,所以叫工厂模式。缺点:我无法识别创建的对象的类型。因为它们都是对象,所以没有区别,不像日期、数组等。因此会出现构造函数模式。
3构造器模式
函数create person(name){ this . name=name;this . show name=function(){ alert(this . name);} } var p1=new CreatePerson('哈哈');P1 . show name();var p2=new CreatePerson('呵呵');p2 . show name();我们通过这两个方面进行改变:
1函数名的第一个字母大写
这是为了区别于普通功能。构造函数本身其实是一个普通的函数,但是我们用它来实现构造的功能,所以我们有一个特殊的名字叫做构造函数。任何函数都可以是构造函数,这取决于调用函数的方式。当你用New方式调用它时,它就变成了一个构造函数。
2新关键字呼叫
调用函数时使用了New关键字,那么New做了什么呢?用不用New有什么区别?让我们看看下面的例子
函数create person(name){ this . name=name;this . show name=function(){ alert(this . name);};console.log(此);}新的CreatePerson('哈哈');//createpersonacreateperson('哈哈');//window我们会发现,用New调用函数时,这点会有所不同。其实New主要做了以下的事情,但是下面写的只是一般的行为,并不是内部的源代码。
函数create person(name){ var obj={ };//声明一个空对象objobj。_ proto _=create person . prototype;//将这个对象的_proto_ attribute指向构造函数的原型对象,这样obj就可以调用CreatePerson原型对象下的所有方法,其中原型首先知道结论,这将在下面描述。create person . apply(obj);//使用apply方法将此指向obj对象this.name=name//将属性添加到//obj对象,这个方法。showname=function () {alert (this。姓名);};返回对象;//返回此对象}函数构造模式中的问题:
alert(P1 . show name==p2 . show name);//false缺点:可以看出这两个对象不共享同一个方法。每次它们是新的,系统都会创建一个新的内存。这两个对象有各自的领地,但是功能相同,还没有共享,这肯定不是我们想要的。于是就有了下一个方法,原型构建模式
4原型构建模式
Prototype:每个函数都有一个prototype属性,它是一个对象,也叫prototype object,我们可以在这个对象上写方法和属性(虽然prototype objects不仅有我们写的属性和方法,还有其他的,下面会描述),这个函数创建的实例对象可以共享这个prototype object下的方法和属性。所以我们只需要把我们想分享的东西放在函数的原型下面,通过构造函数创建我们不想分享的东西。看一个栗子(原型结构)
函数create person(name){ this . name=name;} create person . prototype . show name=function(){ alert(this . name);}var p1=new CreatePerson('哈哈');P1 . show name();var p2=new CreatePerson('呵呵');p2 . show name();alert(P1 . show name==p2 . show name);//true test为真,可以看出showName()方法是共享的,也就是说它们共享一个内存,而且更进一步,它们有一个引用关系,也就是说如果改变p1的showName,也会影响p2的showName。
_proto_ attribute :
同一个函数创建的实例对象可以共享这个函数原型下的方法和属性,但是它是如何做到的呢?这是_proto_ attribute。
每个实例化的对象都有一个_proto_ attribute,它是指向函数原型的指针,也就是保存它的地址。(JS中任何一个对象的值都存储在堆内存中,我们声明的变量只是一个指针,它保存了这个对象的实际地址,所以我们可以找到有地址的对象。)因此,一般来说,每个实例化的对象都有一个_proto_ attribute,它保存了构造函数的原型对象的地址,通过这个属性,我们可以拥有原型对象下的所有属性和方法。_proto_ attribute实际上是实例化对象和原型对象之间的连接。
原型链:
每个函数都可以是构造函数,每个函数都有一个原型对象,每个原型对象也可以是一个实例化的对象。比如你创建一个fun函数,它是构造函数的实例化对象,函数的原型对象也是object的实例对象。所以fun有一个_proto_ attribute来访问函数的原型Object,它也是一个实例对象,也有一个_proto_ attribute来访问对象的原型对象,所以通过_proto_ attribute形成了一个原型链。每个实例化的对象都可以访问链上面的方法和属性,所以fun可以访问对象原型对象下面的方法和属性。几乎所有对象都可以访问对象的原型对象。
原型链的访问规则:先看自己下面,然后一级一级的去原型链。
如下所示:
函数Aaa(){ } Aaa . prototype . num=3;var a1=新Aaa();a1.num=10alert(a1 . num);//10
原型对象:
原型对象下可能有三个属性:
1原型对象携带的方法和属性2构造函数3_proto_ property
Constructor: Constructor属性(每个函数的原型对象的默认属性)指向该函数。
每个实例化的对象本身没有构造函数属性,默认情况下它下面只有一个_proto_ attribute,用于连接原型对象,但与构造函数本身没有直接的联系。所以它的构造函数在被访问的原型对象上。因此,当原型对象的构造函数改变时,实例化对象的构造函数也随之改变。但是,如果对象本身既是原型对象又是实例化对象,则它具有构造函数属性,并且不需要从原型对象访问它。**
请看下面的例子来验证我们所说的:
函数创建个人(姓名){ this。name=name}创建个人。原型。show name=function(){ console。日志(这个。姓名);};var p1=新的CreatePerson('哈哈');P1。show name();控制台。原木(P1。建造师);//创建人来自创建人。原型控制台。日志(createperson。原型);//{ showname : }、constructor:CreatePerson、_ _ proto _ _ :对象。原型}//可见,原型对象保存了一自身添加的方法, 2 构造函数构造函数3 _proto_(和上一层构造函数原型对象的连接)控制台。日志(createperson。原型。_ _ proto _ _===对象。原型);//真这个原型对象本身又是目标的实例化对象,所有_原型_指向目标的原型对象控制台。日志(createperson。原型。_ _ proto _ _===Object);//false可见是和构造函数下原型对象的连接,不是构造函数控制台。日志(创建人。原型。建造师);//CreatePerson CreatePerson。原型是目标实例化对象,也是原型对象,所以自身拥有构造器属性控制台。日志(对象。原型。_ _ proto _ _);//null原型链的终点是nullconsole.log(CreatePerson ._ _ proto _ _);//函数。原型//CreatePerson本身既是构造函数又是功能的实例化对象,拥有_原型_属性,指向功能的原型对象控制台。日志(创建人。建造师);//函数继承自功能。原型控制台。日志(创建人。CreatePerson的原型实例)//验证是否在一条原型链上错误的字面量法定义原型:
为了创建对象的代码更方便,你一定见过这样的代码,就是字面量法:
函数Aaa(){ } Aaa。prototype={ show name : function(){ },show sex : function(){ };var a1=新AAA();控制台。日志(Aaa。原型);//{showName:function(){},_proto_} //你会发现构造器不见了,因为这种方式相当于重新赋值了Aaa。原型控制台。日志(Aaa。原型。建造师);//对象因为自身没有了构造器属性,就去上级原型对象找,找到了对象控制台。日志(a1。建造师);//对象也变了,验证了它是访问的原型对象上的因此我们在写的时候需要修正一下原型的指向:
函数Aaa(){ } Aaa。prototype={ constructor : Aaa,num 1: function(){ alert(10);} } var a1=new Aaa();a1.constructor //Aaa以上所述是小编给大家介绍的JavaScrpt的面向对象全面解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
版权声明:面向对象的JavaScrpt综合分析是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。