您的位置:首页 > Web前端 > JavaScript

[翻译]javascript学习笔记 (四)-面向对象的实现

2007-05-01 01:12 771 查看
javascript中面向对象的实现

javascript中的函数可以充当类的角色,我们用函数的prototype完成类的功能。

首先了解javascript中的对象是如何工作的,对象允许你定义一个变量然后可以在变量上设置任意多的属性

让我们看下一个简单的例子

var myObj = new Object;

myObj.a = 5;

myObj['b'] = 10;

myObj.c = 20;

myObj.getTotal = function(){

alert(this.a+this.b+this.c);

});

// or

var myObj = {a:5, b:10, c:20, getTotal:function(){ alert(this.a+this.b+this.c); }};

这两个代码片段创建了相同的变量,myObj。

当你在一个对象中执行一个函数时,"this"指向对象的引用。

javascript中的对象非常有用,我们写一个animal对象

var myAnimal = {

name: 'felix',

species: 'cat',

talk: function(){ alert('Meow!'); },

callOver: function(){ alert(this.name+' ignores you'); },

pet: function(){ alert('Purr!'); }

}
现在我们定义了一个变量 myAnimal,名字叫felix。当我们想创建另外一只猫,我们学要键入上述所有代码。于是面向对象思想该起作用了。用一个函数生成类似的对象而不是重复的键入代码。



function Cat(name){

this.name = name;

this.species = 'Cat';

this.talk = function(){ alert('Meow!'); }

this.callOver = function(){ alert(this.name+' ignores you'); },

this.pet = function(){ alert('Purr!'); }

}

var felix = new Cat('Felix');

var sam = new Cat('Sam');

var patty = new Cat('Patty');

felix.pet(); // alerts 'Purr!'

sam.callOver(); // alerts 'Sam ignores you'. Just like a cat!

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函数

function Cat(name){

this.name = name;

}

Cat.prototype.species = 'Cat';

Cat.prototype.talk = function(){ alert('Meow!'); };

Cat.prototype.callOver = function(){ alert(this.name+' ignores you'); };

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方法。

function Cat(name){

this.name = name;

}

Cat.prototype = {

species: 'Cat',

talk: function(){ alert('Meow!'); },

callOver: function(){ alert(this.name+' ignores you'); },

pet: function(){ alert('Pet!'); }

}

需要注意的是使用prototype设置方法会替代以前设置的方法。如果我们通过这种方式添加一个sleep方法

Cat.prototype = {

sleep: function(){ alert(this.name+' falls asleep'); }

}

我们前面的prototypes,species,talk,callOver和pet都将被清除,我们cat的原型方法只有sleep

Prototypes也可以用来扩展javascript内置的对象。我们能实现一个String.prototype.reverse方法

String.prototype.reverse = function(){

var out = '';

for(var i=this.length-1; i>=0; i--){

out+=this.substr(i, 1);

}

return out;

}

alert('asdf'.reverse());
如果恰当的使用它,将会很有用。

强烈建议不要在array和object中使用prototype,因为这样会影响"for-in"语句的使用。看看下面的例子:

var myArray = [1, 2, 3];

for(n in myArray) alert(n); // alerts 0, 1 and 2 - the indexes of the array.

Array.prototype.something = function(){ };

for(n in myArray) alert(n); // alerts 'something', 0, 1 and 2.

有其他方法可以达到相同的效果,我个人不喜欢使用prototype扩展array

Array.find = function(ary, element){

for(var i=0; i<ary.length; i++){

if(ary[i] == element){

return i;

}

}

return -1;

}

alert(Array.find(['a', 'b', 'c', 'd', 'e'], 'b')); // alerts 1

如你所见,我们使用Array.find(ary, e)替代ary.find(e),额外的一点代码换来的是不破坏现有javascript的功能性。

Private, Public 和 Static 变量

PrivateDeclared
with 'var variableName' or 'function functionName' inside of the
object. Can only be accessed by other private or privileged functions.
PublicDeclared with 'this.variableName' inside of the object. Can be changed by any function or method.
PrivilegedDeclared
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.
PrototypeDeclare
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.
StaticDeclare
with 'Class.variableName' or 'Class.functionName'. Can be changed by
any function or method. This method is rarely used.
为了理解不同级别,看看下面的例子

function Cat(name, color){

/*

Constructor: any code in here is run when the object is created

*/

Cat.cats++;

/*

Private variables and functions - may only be accessed by private or privileged functions.

Note that 'name' and 'color', passed into the Class, are already private variables.

*/

var age = 0;

var legs = 4;

function growOlder(){

age++;

}

/*

Public variables - may be accessed publicly or privately

*/

this.weight = 1;

this.length = 5;

/*

Privileged functions - may be accessed publicly or privately

May access Private variables.

Can NOT be changed, only replaced with public versions

*/

this.age = function(){

if(age==0) this.length+=20;

growOlder();

this.weight++;

}

}

/*

Prototyped Functions - may be accessed publicly

*/

Cat.prototype = {

talk: function(){ alert('Meow!'); },

callOver: function(){ alert(this.name+' ignores you'); },

pet: function(){ alert('Pet!'); }

}

/*

Prototyped Variables - may be accessed publicly.

May not be overridden, only replaced with a public version

*/

Cat.prototype.species = 'Cat';

/*

Static variables and functions - may be accessed publicly

*/

Cat.cats = 0;

这里有许多访问限制级别,所有的private,privileged和public函数和变量都会在创建新的实例时被拷贝。通常可以使用prototype和public变量可以完成所有的任务。

Created by jecray
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐