JavaScript中的面向对象技术

使用JavaScript进行面向对象编程

JS的一个例子使用JS实现一个集合类

集合(Set)是一种数据结构,使用表示非重复值的无须集合。集合的基础方法包含添加值、检查值和是否在集合中,这种集合需要一种通用的实现,以保证操作效率,这种集合需要一种通用的实现,以保证操作效率。

JS的一个例子使用JS实现一个枚举类型

枚举类型(enumerated type)是一种类型,它是值的一种有限集合,如果值定义为这个类型则该值是可以列出(或可以"枚举")的;

在ECMAScript5中如何定义一个枚举类型

JS中的标准转换方法

对象类型转换所用到的重要方法,有一些方法是在类做类型转换时JavaScript解释器自动调用的,不需要为定义的每个类都实现这些方法,但这些方法是非常重要的,如果没有这些方法,也应当是有意而为之,不是因为疏忽而漏掉他们。
1.最重要的首先是toString()方法,这个方法是将类返回一个可读的字符串。如果没有实现这个方法,JavaScript会从Object.prototype中继承toString()方法.
实现一个toString方法.
2.toLocaleString()和toString()极为相似:toLocaleString()是以本地敏感性(locale-sensitive)的方式将对象转换为字符串。
3.valueOf(),它用来将对象转换为原始值。比如,当数学运算符(除了使用“+”运算符)和关系运算符作用于数字文本对象时,会自动调用valueOf()方法。
4.toJSON(),JSON.stringify()自动调用。JSON格式用于序列化良好的数据结构,而且可以处理JavaScript原始值,数组和纯对象。他和类无关,当对一个对象执行序列化操作时,他会忽略对象的原型和构造函数。

JS的比较方法

1.JavaScript的相等运算符比较对象时,比较的是引用而不是值。也就是说,给定两个对象引用,如果看他们是否指向同一个对象,不是检查这两个对象是否具有相同的属性名和相同的属性值,如果定义一个类,并且希望比较类的实例,应该定义合适的方法来执行比较操作。

//借助Java的思想给Rangs类编写equals();
Range.prototype.constructor=Range;
//一个Range对象和其他不是Range的对象均不相等
//当且仅当两个范围的端点相等,它们才相等
Range.prototype.equals =function(that){
    if(that==null) return false;
    if(that.constructor !==Range) return false;
    return this.from == that.from && this.to ==that.to;
}
Set.prototype.equals =function(that){
//一些次要情况的快捷键
if(this === that )return true;
//如果that对象不像是一个集合,它和this不相等
//我们用到了instanceof,使得这个方法可以用于Set的任何子类
//如果希望法采用鸭式辩型的方法,可以降低检查的严格程度
//或者可以通过this.contructor ==that.contructor 来加强检查的严格程度
//注意,null和underfined两个值是无法用于instanceof运算的
if(!(that instanceof Set)) return false;
//如果两个集合的大小不一样,则他们不相等
if(this.size()!=that.size())return false;
try {
    this.foreach(function(v){if (!that.contains(v)) throw false;});
}catch(x){
    if(x===false) return false;
    throw x;
}
}

2.对于用于比较大小的我们通常使用compareTo()方法进行比较,compareTo()的方法应当只能接受一个参数,这个方法将这个参数和调用它的对象进行比较。

对Range的方法进行比较

Range.prototype.compareTo =function(that){
return this.from -that.from;
};

需要注意的是,这个方法中的加法操作根据两个Range对象的关系返回了小于,大于,等于0的值。

同时,equals()方法和compareTo方法的基本处理逻辑应该保持一致.给Range对象排序。

Range.prototype.compareTo =function(that){
    if(!(that instanceof Range))
    throw new Error("Can't compare a Range with"+that);
    var diff =this.from -that.from;
    if(diff ==0 )diff =this.to -that.to;
    return diff;
}
//使用compareTo()和排序方法
ranges.sort(function(a,b){return a.compareTo(b)});

方法的借用

多个类中的方法可以共用一个单独的函数,比如,Array类通常定义了一些内置方法,如果定义了一个类,它的实例是类数组的对象,则可以从Array.prototype中将函数复制至所定义的类的原型对象中。如果以经典的面向对象语言的是叫来看JavaScript的话,把一个类的方法用到其他的类中的方法也称做"多重继承"(multiple inheritance).JavaScript并不像经典的面向对象语言,我更倾向于将这种方法重用正式地称之为"方法借用"(borrowing).

不仅Array的方法可以借用,还可以自定义泛型方法(generic method).如Range类借用equals方法

Range.prototype.equals =generic.equals;

var generic ={
toString:function(){
var s =’[’;
if(this.constructor && this.constructor.name)
s +=this.constructor.name+":";
//枚举所有的非继承且非函数的属性
var n =0;
for(var name in this){
if(!this.hasOwnProperty(name)) continue;
var value =this[name];
if (typeof value ===“function”) continue;
if(n++) s+=",";
s +=name+’=’+value;
}
return s+’]’;
}
equals:function(that){
if(that == null) return false;
if(this.constructor !==that.constructor) return false;
if(this[name] !==that[name]) return false;
}
return true;
}

JS中的私有属性

1.在经典的面向对象编程中,经常需要将对象的某个状态封装或隐藏在对象内,只有通过对象的方法才能访问这些状态。对外只暴露一些重要的状态变量可以直接读写。为了实现这个目的,类似Java的变成语言允许声明类的“私有”实例字段,这些私有实例字段只能被类的实例方法访问,且在类的外部是不可见的。

//通过闭包来模拟私有属性
function Range(from,to){
this.from=function(){return this.from};
this.to=function(){return this.to};
}
//在原型对象上使用this.from(),和this.to()来获取构造方法中的参数值。
Range.prototype={
    constructor:Range,
    includes:function(x){return this.from()<=x&& x<=this.to();},
    foreach:function(f){for(var x=Math.ceil(this.from(),max=this.to();x<=max;x++)f(x))},
    toString:function(){return "("+this.from()+"..."+this.to()+")";}
};

通过闭包这样封装的状态会让计算速度更慢,并且更占内存。

构造函数的重载和工厂方法

有时候我们希望通过参数的不同来让初始化方法传入不同的参数执行不同的初始化方法。
例如:

function Set(){
    this.values={};
    this.n=0;
if(arguments.length==1&&isArrayLike(argments[0])){
    this.add.apply(this,argumments[0]);
}
else if(arguments.length>0)
    this.add.apply(this,argumens);
}
//使用工厂方法来返回一个集合
Set.fromArray =function(a){
    s = new Set();
    s.add.apply(s,a);
    return s;
}

//不推荐使用一个类拥有多个构造函数,但不是“必须的”。
//使用该技术实现一个辅助构造函数

//Set类的一个辅助构造函数
function SetFromArray(a){
    Set.apply(this,a);
}
//设置原型,以便SetFromArray能创建Set的实例
SetFromArray.prototype=Set.prototype;
var s =new SetFromArray([1,2,3]);
s instanceof Set 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值