天天看点

JavaScript中的“类”

原文:JavaScript classes

    JavaScript是一种功能强大而优雅的语言,它拥有许多很好的特点,然而,有一个特点是它所不具备的,那就是“类”,至少在它的静态类型上没有经典继承的语义。但是,JavaScript有一个健状的对象原型(prototype)系统,这也是本文探讨的基础。

    开始吧,考虑下面这个简单的JavaScript函数:

function Person( name ){
	this.name = name;
}      

    从上面的代码可以了解,在JavaScript中,函数除了发挥它们通常的作用外,还是JavaScript中原型(prototype)的基础。我们可以使用如下代码创建新的Person实例:

var bob = new Person( "Bob");
var alice = new Person( "Alice");      

   在这里要指出的是,bob是一个从Person的原型中创建的对象。如果我们访问bob.name会发现它包含字符串“Bob”。bob对象拥有一些可用方法,像toString(),它们都是从Object中继承而来的(稍后更多介绍)。

   与其它经典的静态类型继承语言(Java,C#)中的类不同,JavaScript中的原型(prototypes)是可以修改的,它的每个实例都会相应的应用这种改变。假设我们想要Person的所有实例都有一个greet()方法,可以用以下代码达到目的:

Person.prototype.greet = function( otherPerson ){
	alert( "Hello " + otherPerson.name + ", I'am " + this.name );
}      

   现在我们有了两个可以相互问候的Person,bob和alice:

bob.greet( alice ); // alerts "Hello Alice, I'm Bob"
alice.greet( bob ); // alerts "Hello Bob, I'm Alice"      

   当我们调用 bob.greet()方法时,JavaScript引擎会在下面的位置查找 greet 函数:

       1.bob自身的属性(成员)(如同 bob.name)

       2.Person.prototype的属性

       3.Object.prototype的属性

   JavaScript引擎在找到作为Person.prototype属性的greet后将不再查找,另外,如果调用 bob.toString()则会强制JavaScript引擎沿着上面的路径向上查找,直到在Object.prototype中找到一个相匹配的。我们也可以通过在Person.prototype中定义toString()重载其行为。

Person.prototype.toString = function(){
	return this.name.toString();
};      

    前面列出的三个位置是JavaScript运行时查找属性的唯一地方,换句话说,在面向对象的语言中以创建父类的子类的方式来继承,而JavaScript并不会天生的像这样支持原型到原型的继承。当然,JavaScript也足够强大,它允许使用框架或库以不同的形式来覆盖继承模式。例如,一种方式,复制一个原型的成员到另一个原型,另一种高级些的方式,捕获属性查找事件,然后沿着一个特别维护的继承链查找,返回第一个匹配的属性。本文只作介绍性的提及,这两种方法都已经超出了本文的介绍范围。

    本文将注意力完全集中在JavaScript中的“类”的入门上,我希望这里的介绍能建立起一些概念,在将来的文章中再来深入剖析,如,关键字“new”的内部工作方式。

继续阅读