尽管Java、C++和JavaScript都是面向对象的语言,但JavaScript中的类和前两者有很大的不同。在JavaScript中,类的实现是基于原型机制的。接下来我们来看看两种定义类的方法:
1 类和原型
在JavaScript中,类的所有实例对象都会从一个原型对象上继承属性。因此原型对象是类的属性。我们来看一个简单的例子,下面定义了一个简单的JavaScript类:
function inherit(p){//inherit()用于创建新对象 if(p == null) throw TypeError(); if(Object.create) return Object.create(p); var t = typeof p; if(t !== "object" && t !== "function") throw TypeError(); function f(){}; f.prototype = p; return new f(); } function range(from, to){//创建一个工厂函数 var r = inherit(range.method); r.from = from; r.to = to; return r; } range.method = {//原型对象定义方法,这些方法为每个范围对象所继承 includes: function(x){ return this.from<=x && x<=this.to; }, foreach: function(f) { for (var i = Math.ceil(this.from); i <= this.to; i++) f(i); }, toString: function(){return "("+this.from + "..." + this.to + ")";} }; var r = range(1, 3);//创建一个范围对象 r.includes(2);//->true: 2在这个范围内 r.foreach(console.log);//输出1 2 3 console.log(r);//输出(1...3)
这段代码定义了一个工厂函数range(),用来创建新的对象。这种定义类的方法并不常用,接下来看看另一种定义类的方法。
2 类和构造函数
还是上面的例子,但我们用构造函数的方式来构建类,构造函数用来初始化新创建的对象。然后用Range.prototype创建原型对象:
例1:
function Range(from, to) { this.from = from; this.to = to; } Range.prototype = { constructor: Person,//显式设置构造函数反向引用 includes: function(x){ return this.from<=x && x<=this.to; }, foreach: function(f) { for (var i = Math.ceil(this.from); i <= this.to; i++) f(i); }, toString: function(){return "("+this.from + "..." + this.to + ")";} };var r = range(1, 3);//创建一个范围对象 r.includes(2);//->true: 2在这个范围内 r.foreach(console.log);//输出1 2 3 console.log(r);//输出(1...3)
例2:创建一个个人的信息类
//创建一个人的信息类 function Person(name, sex, age){ this.name = name; this.sex = sex; this.age = age; } Person.prototype = {//给原型对象添加方法
constructor: Person,//显式设置构造函数反向引用 wife: function(str) { this.name = str; return this.name; }, son: function(str) { this.name = str; this.name;}};//定义一个新对象,这个对象继承了(prototype)原型对象的所有方法 var man = new Person('Bruce', 'male', '25'); var wife = man.wife('Jane'); var son = man.son('Brand'); console.log( man ); console.log( man.name + "'s" + " wife is " + wife ); console.log( man.name + "'s" + "son is " + son );
其输出结果:
这种方法还有另一种方式来构造类,好处就是不用显示的设置构造函数的反向引用,以例2为例:
//创建一个人的信息类 function Person(name, sex, age){ this.name = name; this.sex = sex; this.age = age; }; //依次给原型对象添加方法 Person.prototype.wife = function(str) { this.name = str; return this.name; } Person.prototype.son = function(str) { this.name = str; return this.name; } //定义一个新对象,这个对象继承了(prototype)原型对象的所有方法 var man = new Person('Bruce', 'male', '25'); var wife = man.wife('Jane'); var son = man.son('Brand'); console.log( man ); console.log( man.name + "'s" + " wife is " + wife ); console.log( man.name + "'s" + "son is " + son );其输出结果是一样的,例1也可按照这种方改为这种方式。