对象构造器和原型
OOP(面向对象编程Object-Oriented Programming)世界中,早先用来定义对象的方法存在着诸多限制。我们需要一种方法: 创建能够多次复用的类型而不需要每次都针对特定实例的需要而重新定义对象。而标准的方法就是使用对象构造函数。
对象构造器其实就是一个常规的JavaScript 函数,所以拥有一样的健壮性(定义参数,调用其它函数等)。区别在于构造函数是通过new操作符来调用的(下面就会看到)。而同样基于函数语法定义的对象自然也具有同样的健壮性。
让我们拿真实世界中的“猫”来举个例子。猫的属性可能是它的颜色或是名字。而方法可能就是叫一声“喵”。此处需要说明的是,每只猫都会有不同的名字甚至它们的叫声也不相同。使用对象构造器就可以创建出适应这种需求的对象类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <script language="javascript" type="text/javascript"> <!--
function cat(name) { this.name = name; this.talk = function() { alert( this.name + " say meeow!" ) } }
cat1 = new cat("felix") cat1.talk() //alerts "felix says meeow!"
cat2 = new cat("ginger") cat2.talk() //alerts "ginger says meeow!"
//--> </script> |
上述代码中的函数cat()就是一个对象构造器,它的属性与方法通过使用"this."作为前缀在构造函数内定义。使用"new"关键字来实例化那些使用对象构造器定义的对象。注意我们是如何轻松地为cat定义出不同实例的,每个实例都有自己的名字 -- 而这个灵活性就是由对象构造器带给自定义对象的。构造器是创建对象模板而不是对象本身。
使用原型来为我们的对象添加方法
上文中我们看到了如何通过在构造函数内部通过声明的方式来添加方法。而另外一种方法就是通过原型,原型也因为其优雅的写法而更多的被采用。原型(Prototype)是javascript中的一个继承类型。当我们想要一个对象在被定义后再去继承一个方法的时候,就可以使用原型了。可以把这种原型的使用想象成附加一个方法到一个已经定义好的对象上,而所有对象实例都可以共享该方法。
让我们来扩展一下上例中的cat()对象,通过原型(prototype)给它添加一个用来修改名字的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <script language="javascript" type="text/javascript"> <!--
cat.prototype.changeName = function(name) { this.name = name; }
firstCat = new cat("pursur") firstCat.changeName("Bill") firstCat.talk() //alerts "Bill says meeow!"
//--> </script> |
正如你所看到的,我们仅仅是在对象名字后面加上了关键字"prototype"就使用了该功能。现在所有的cat实例都可以使用自定义方法changeName()了。
在预建javascript对象上使用原型(prototype)
原型对于自定义对象与预建对象都有效,如Date()或是String。 总的原则是你可以在任意使用'new'关键字初始化的预建对象上使用prototype。我来演示一下给预建对象Array添加额外功能。
IE5不支持Array的shift()和unshift()方法,而NS4+支持。让我们通过prototype来添加它们!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <script language="javascript" type="text/javascript"> <!--
// The shift() and unshift() methods.
if(!Array.prototype.shift) { // if this method does not exist..
Array.prototype.shift = function(){ firstElement = this[0]; this.reverse(); this.length = Math.max(this.length-1,0); this.reverse(); return firstElement; }
}
if(!Array.prototype.unshift) { // if this method does not exist..
Array.prototype.unshift = function(){ this.reverse();
for(var i=arguments.length-1;i>=0;i--){ this[this.length]=arguments[i] }
this.reverse(); return this.length } }
//--> </script> |