javascript中面向对象的实现
javascript中的函数可以充当类的角色,我们用函数的prototype完成类的功能。
首先了解javascript中的对象是如何工作的,对象允许你定义一个变量然后可以在变量上设置任意多的属性
让我们看下一个简单的例子
这两个代码片段创建了相同的变量,myObj。
当你在一个对象中执行一个函数时,"this"指向对象的引用。
javascript中的对象非常有用,我们写一个animal对象

上面的例子我们创建了一个函数cat,然后用函数创建了3个新的cat对象:felix,sam和patty。每个cat都有相同的函数:talk,callOver和pet,都有自己的species属性。
我们通常说felix,sam和patty是相同对象的实例。cat函数中的代码是构造函数。接收"name"用来设置this.name。但是在每个 cat构造的时候,我们实际上创建了每个方法的3个副本。由于talk,callOver和pet方法是相同的,我们只需每个方法的一个副本。
我们使用Prototyping重写cat函数

上面函数的语法和以前的有些不同。现在可以用Cat.prototype定义属性和方法,而不是在函数体内定义。虽然这样复杂了,但是它提供了很多优点。假设我们给现有的每个cat加一个新的方法sleep 有两种方法:
第一种是跟踪每个cat,给每个cat加入方法。
第二种是使用prototype,我们可以同时为每个cat加入sleep方法
Cat.prototype.sleep = function(){ alert(this.name+' falls asleep'); };
这种方法不但快捷,而且不需要跟踪每个cat去添加sleep方法。
需要注意的是使用prototype设置方法会替代以前设置的方法。如果我们通过这种方式添加一个sleep方法
我们前面的prototypes,species,talk,callOver和pet都将被清除,我们cat的原型方法只有sleep
Prototypes也可以用来扩展javascript内置的对象。我们能实现一个String.prototype.reverse方法
强烈建议不要在array和object中使用prototype,因为这样会影响"for-in"语句的使用。看看下面的例子:
有其他方法可以达到相同的效果,我个人不喜欢使用prototype扩展array
如你所见,我们使用Array.find(ary, e)替代ary.find(e),额外的一点代码换来的是不破坏现有javascript的功能性。
Private, Public 和 Static 变量
为了理解不同级别,看看下面的例子
这里有许多访问限制级别,所有的private,privileged和public函数和变量都会在创建新的实例时被拷贝。通常可以使用prototype和public变量可以完成所有的任务。
javascript中的函数可以充当类的角色,我们用函数的prototype完成类的功能。
首先了解javascript中的对象是如何工作的,对象允许你定义一个变量然后可以在变量上设置任意多的属性
让我们看下一个简单的例子
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->varmyObj=newObject;
myObj.a=5;
myObj['b']=10;
myObj.c=20;
myObj.getTotal=function(){
alert(this.a+this.b+this.c);
});
//or
varmyObj={a:5,b:10,c:20,getTotal:function(){alert(this.a+this.b+this.c);}};
myObj.a=5;
myObj['b']=10;
myObj.c=20;
myObj.getTotal=function(){
alert(this.a+this.b+this.c);
});
//or
varmyObj={a:5,b:10,c:20,getTotal:function(){alert(this.a+this.b+this.c);}};
这两个代码片段创建了相同的变量,myObj。
当你在一个对象中执行一个函数时,"this"指向对象的引用。
javascript中的对象非常有用,我们写一个animal对象
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->
varmyAnimal={
name:'felix',
species:'cat',
talk:function(){alert('Meow!');},
callOver:function(){alert(this.name+'ignoresyou');},
pet:function(){alert('Purr!');}
}
现在我们定义了一个变量 myAnimal,名字叫felix。当我们想创建另外一只猫,我们学要键入上述所有代码。于是面向对象思想该起作用了。用一个函数生成类似的对象而不是重复的键入代码。 varmyAnimal={
name:'felix',
species:'cat',
talk:function(){alert('Meow!');},
callOver:function(){alert(this.name+'ignoresyou');},
pet:function(){alert('Purr!');}
}

<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->functionCat(name){
this.name=name;
this.species='Cat';
this.talk=function(){alert('Meow!');}
this.callOver=function(){alert(this.name+'ignoresyou');},
this.pet=function(){alert('Purr!');}
}
varfelix=newCat('Felix');
varsam=newCat('Sam');
varpatty=newCat('Patty');
felix.pet();//alerts'Purr!'
sam.callOver();//alerts'Samignoresyou'.Justlikeacat!
alert(patty.species);//alerts'cat'
this.name=name;
this.species='Cat';
this.talk=function(){alert('Meow!');}
this.callOver=function(){alert(this.name+'ignoresyou');},
this.pet=function(){alert('Purr!');}
}
varfelix=newCat('Felix');
varsam=newCat('Sam');
varpatty=newCat('Patty');
felix.pet();//alerts'Purr!'
sam.callOver();//alerts'Samignoresyou'.Justlikeacat!
alert(patty.species);//alerts'cat'
上面的例子我们创建了一个函数cat,然后用函数创建了3个新的cat对象:felix,sam和patty。每个cat都有相同的函数:talk,callOver和pet,都有自己的species属性。
我们通常说felix,sam和patty是相同对象的实例。cat函数中的代码是构造函数。接收"name"用来设置this.name。但是在每个 cat构造的时候,我们实际上创建了每个方法的3个副本。由于talk,callOver和pet方法是相同的,我们只需每个方法的一个副本。
我们使用Prototyping重写cat函数
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->functionCat(name){
this.name=name;
}
Cat.prototype.species='Cat';
Cat.prototype.talk=function(){alert('Meow!');};
Cat.prototype.callOver=function(){alert(this.name+'ignoresyou');};
Cat.prototype.pet=function(){alert('Purr!');};
this.name=name;
}
Cat.prototype.species='Cat';
Cat.prototype.talk=function(){alert('Meow!');};
Cat.prototype.callOver=function(){alert(this.name+'ignoresyou');};
Cat.prototype.pet=function(){alert('Purr!');};

上面函数的语法和以前的有些不同。现在可以用Cat.prototype定义属性和方法,而不是在函数体内定义。虽然这样复杂了,但是它提供了很多优点。假设我们给现有的每个cat加一个新的方法sleep 有两种方法:
第一种是跟踪每个cat,给每个cat加入方法。
第二种是使用prototype,我们可以同时为每个cat加入sleep方法
Cat.prototype.sleep = function(){ alert(this.name+' falls asleep'); };
这种方法不但快捷,而且不需要跟踪每个cat去添加sleep方法。
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->functionCat(name){
this.name=name;
}
Cat.prototype={
species:'Cat',
talk:function(){alert('Meow!');},
callOver:function(){alert(this.name+'ignoresyou');},
pet:function(){alert('Pet!');}
}
this.name=name;
}
Cat.prototype={
species:'Cat',
talk:function(){alert('Meow!');},
callOver:function(){alert(this.name+'ignoresyou');},
pet:function(){alert('Pet!');}
}
需要注意的是使用prototype设置方法会替代以前设置的方法。如果我们通过这种方式添加一个sleep方法
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->Cat.prototype={
sleep:function(){alert(this.name+'fallsasleep');}
}
sleep:function(){alert(this.name+'fallsasleep');}
}
我们前面的prototypes,species,talk,callOver和pet都将被清除,我们cat的原型方法只有sleep
Prototypes也可以用来扩展javascript内置的对象。我们能实现一个String.prototype.reverse方法
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->String.prototype.reverse=function(){
varout='';
for(vari=this.length-1;i>=0;i--){
out+=this.substr(i,1);
}
returnout;
}
alert('asdf'.reverse());
如果恰当的使用它,将会很有用。varout='';
for(vari=this.length-1;i>=0;i--){
out+=this.substr(i,1);
}
returnout;
}
alert('asdf'.reverse());
强烈建议不要在array和object中使用prototype,因为这样会影响"for-in"语句的使用。看看下面的例子:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->varmyArray=[1,2,3];
for(ninmyArray)alert(n);//alerts0,1and2-theindexesofthearray.
Array.prototype.something=function(){};
for(ninmyArray)alert(n);//alerts'something',0,1and2.
for(ninmyArray)alert(n);//alerts0,1and2-theindexesofthearray.
Array.prototype.something=function(){};
for(ninmyArray)alert(n);//alerts'something',0,1and2.
有其他方法可以达到相同的效果,我个人不喜欢使用prototype扩展array
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->Array.find=function(ary,element){
for(vari=0;i<ary.length;i++){
if(ary[i]==element){
returni;
}
}
return-1;
}
alert(Array.find(['a','b','c','d','e'],'b'));//alerts1
for(vari=0;i<ary.length;i++){
if(ary[i]==element){
returni;
}
}
return-1;
}
alert(Array.find(['a','b','c','d','e'],'b'));//alerts1
如你所见,我们使用Array.find(ary, e)替代ary.find(e),额外的一点代码换来的是不破坏现有javascript的功能性。
Private, Public 和 Static 变量
| Private | Declared with 'var variableName' or 'function functionName' inside of the object. Can only be accessed by other private or privileged functions. |
| Public | Declared with 'this.variableName' inside of the object. Can be changed by any function or method. |
| Privileged | Declared with 'this.functionName = function(){ ... }' inside of the object. Can be accessed by any function or method and can call reference or change any Private variable. |
| Prototype | Declare with 'Class.prototype.variableName' or 'Class.prototype.functionName'. Functions declared this way will have access to any public or prototype variables. Attempts to change variable created this way will instead create a new public variable on the object and the prototype variable will be unavailable. |
| Static | Declare with 'Class.variableName' or 'Class.functionName'. Can be changed by any function or method. This method is rarely used. |
为了理解不同级别,看看下面的例子
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->functionCat(name,color){
/*
Constructor:anycodeinhereisrunwhentheobjectiscreated
*/
Cat.cats++;
/*
Privatevariablesandfunctions-mayonlybeaccessedbyprivateorprivilegedfunctions.
Notethat'name'and'color',passedintotheClass,arealreadyprivatevariables.
*/
varage=0;
varlegs=4;
functiongrowOlder(){
age++;
}
/*
Publicvariables-maybeaccessedpubliclyorprivately
*/
this.weight=1;
this.length=5;
/*
Privilegedfunctions-maybeaccessedpubliclyorprivately
MayaccessPrivatevariables.
CanNOTbechanged,onlyreplacedwithpublicversions
*/
this.age=function(){
if(age==0)this.length+=20;
growOlder();
this.weight++;
}
}
/*
PrototypedFunctions-maybeaccessedpublicly
*/
Cat.prototype={
talk:function(){alert('Meow!');},
callOver:function(){alert(this.name+'ignoresyou');},
pet:function(){alert('Pet!');}
}
/*
PrototypedVariables-maybeaccessedpublicly.
Maynotbeoverridden,onlyreplacedwithapublicversion
*/
Cat.prototype.species='Cat';
/*
Staticvariablesandfunctions-maybeaccessedpublicly
*/
Cat.cats=0;
/*
Constructor:anycodeinhereisrunwhentheobjectiscreated
*/
Cat.cats++;
/*
Privatevariablesandfunctions-mayonlybeaccessedbyprivateorprivilegedfunctions.
Notethat'name'and'color',passedintotheClass,arealreadyprivatevariables.
*/
varage=0;
varlegs=4;
functiongrowOlder(){
age++;
}
/*
Publicvariables-maybeaccessedpubliclyorprivately
*/
this.weight=1;
this.length=5;
/*
Privilegedfunctions-maybeaccessedpubliclyorprivately
MayaccessPrivatevariables.
CanNOTbechanged,onlyreplacedwithpublicversions
*/
this.age=function(){
if(age==0)this.length+=20;
growOlder();
this.weight++;
}
}
/*
PrototypedFunctions-maybeaccessedpublicly
*/
Cat.prototype={
talk:function(){alert('Meow!');},
callOver:function(){alert(this.name+'ignoresyou');},
pet:function(){alert('Pet!');}
}
/*
PrototypedVariables-maybeaccessedpublicly.
Maynotbeoverridden,onlyreplacedwithapublicversion
*/
Cat.prototype.species='Cat';
/*
Staticvariablesandfunctions-maybeaccessedpublicly
*/
Cat.cats=0;
这里有许多访问限制级别,所有的private,privileged和public函数和变量都会在创建新的实例时被拷贝。通常可以使用prototype和public变量可以完成所有的任务。
本文介绍JavaScript中面向对象的实现方式,包括如何利用函数作为构造器创建对象实例,并使用原型(prototype)来共享方法,减少内存消耗。此外还讨论了私有、公共及静态变量的区别。
96

被折叠的 条评论
为什么被折叠?



