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

JavaScript中的Java式继承

2014-11-02 18:38 113 查看

JavaScript中的Java式继承

在面向对象编程中,类是核心部分。在JavaScript面向对象编程中没有提供定义类的方式(java提供了class关键字来定义一个类),但是在JavaScript中可以通过其它方式来模拟类。下面我们就来讲一下怎样在JavaScript中模拟类。注:以下内容是学习《JavaScript 权威指南 第六版》9.3节的学习笔记。

如果你有过java或其它强类型面向对象语言的开发经营,在你的脑海中,类成员的模样可能是这样:
实例字段:它们是基于实例的属性和变量,用以保存独立对象的状态。
实例方法:它们是 类的所有实例共享的方法,由每个独立的实例调用。
类字段(相当于静态字段):这些属性是属于类的,而不是属于类的某个实例。
类方法(想当于静态方法):这些方法是属于类的,而不是属于类的某个实例。
为了便于理解以上内容,我们用java代码实现一个 表示值范围的类,然后再用JavaScript来实现。
表示值范围的类(java版)
package cn.com.hitsoftware;

import java.util.ArrayList;
import java.util.Arrays;

public class Range {
//数据成员(属性)
private int from;	//"范围对象"的起始位置
private int to;		//"范围对象"的开始位置

//构造函数
public Range(int from,int to) throws Exception{
if(from<Range.minFrom || to>Range.maxTo)
throw new Exception(from+"~"+to+"超出了对象所能表示的范围");
this.from = from;
this.to = to;
}

//数据方法
/**
* x在范围之内返回true,否则fasle
*/
public boolean includes(int x){
return from<=x && x<=to;
}
/**
* 返回范围内的所有数据
*/
public ArrayList<Integer> foreach(){
ArrayList<Integer> array = new ArrayList<Integer>();
for(int i=from;i<to;i++)
array.add(i);
return array;
}
/**
* 返回表示这个范围的字符串
*/
public String toString(){
return "("+from+"..."+to+")";
}

//(3)类字段
public static final int minFrom = 1;	//"范围对象"的起始位置最小值
public static final int maxTo = 1000;	//"范围对象"的起始位置最大值

//(4)类方法
/**
* 已数组中元素的最大值和最小值最创建一个"范围对象"
*/
public static Range getRangeByArray(int[] array) throws Exception{
Arrays.sort(array);
return new Range(array[0],array[array.length-1]);
}

public static void main(String [] args){
try {
Range r1 = new Range(1,1000); //(1)from、to就是 r1的实例字段,来标示每个实例独有的from和to(虽然是私有不能通过实例来访问)
System.out.println(r1.toString());//(2)这里toString就是r1实例的方法 (

int[] array = {2,2,1,64,44,90,12};
Range r2 = Range.getRangeByArray(array);
System.out.println(r2.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}


表示值范围的类(JavaScript版)
在JavaScript中模拟类需要用到JavaScrpt中的构造函数、原型对象和实例的的知识。这里对这个三个知识点进行简单的概括:
构造函数:构造函数为JavaScript定义了类名。添加到构造函数对象的属性就是类字段和方法(如果属性值是函数的话就是类方法)。
原型对象:原型对象上的属性和方法会被所有实例继承。属性会被类的当做实例字段来调用,方法会被类实例当做实例方法来调用。
这里插一句。共享属性和方法都放在原型对象上。每个实例独有的状态(对本例来讲就是from和to)都放在构造函数中,这样每次new 构造函数都会初始独有的状态。
实例对象:每个实例都是一个独立的对象。直接在实例上定义属性是不会为其它实例共享的。
//实现一个表示值范围的类
//定义个表示值范围的类
function Range(from,to){
if(from<Range.minFrom || to>Range.maxTo)
throw new TypeError(Range.minFrom+"~"+Range.maxTo+"超出了对象所能表示的范围");
this.from = from;
this.to = to;
}
//将需要共享的属性和方法放到原型对象上
//这样所有的实例都会共享原型对象上的属性和方法
Range.prototype = {
constructor: Range,
includes: function(x){
return this.from<=x && x<=this.to;
},
foreach: function(){
for(var x=this.from,a=[];x<=this.to;x++) a.push(x);
return a;
},
toString: function(){ return '('+this.from+'...'+this.to+')'; }
}
//(3)类字段
Range.minFrom = 1;
Range.maxTo = 1000;

//(4)类方法
Range.getRangeByArry = function(array){
array.sort(function(a,b){ return a-b });
return new Range(array[0],array[array.length-1]);
}
console.log("测试一===========================");
var r1 = new Range(1,100);
console.log(r1.includes(4));
console.log(r1.foreach());
console.log(r1.toString());
console.log(r1.constructor === Range);

console.log("测试二===========================");
var r2 = Range.getRangeByArry([1,90,45,209,1,5,8,4]);
console.log(r2.includes(4));
console.log(r2.foreach());
console.log(r2.toString());//(2)这里toString()就是实例方法,从原型对象继承来的
console.log(r2.constructor === Range);
console.log("from:"+r2.from+"  to:"+r2.to);//(1)r2.from、r2.to就是实例字段,javascript中没有像java提供private关键字,所有我们能通过实例来访问


javascript没有private关键字将属性定义为私有,但是通过闭包可以模拟私有属性。通过ECMAScript 5的新特性可以实现java中的final关键字,让属性只读,不允许修改。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息