javascript中创建不可变的类以及命名空间的定义

我们知道,在javascript中通常实例化一个类时,所产生的对象其属性是可以变的,也就是可以把它删除,但通过使用ECMAScript中的一些工具方法,可以将这些对象属性封装得更好;而当我们想开发一个工具库时,就要涉及到模块的概念,模块避免我们的工具库对命名空间的污染。
一、定义一个不可变的类

function Range(from,to){
    var props = {
        from:{value:from,writable:false,configurable:false,enumerable:true},
        to:{value:to,writable:false,configurable:false,enumerable:true}
    };
    if(this instanceof Range){
        Object.defineProperties(this,props);
    }
    else{
        return Object.create(Range.prototype,props);
    }
}
Object.defineProperties(Range.prototype,{
    includes:{
    value:function(x){
        return x>=this.from&&x<=this.to;
    }},
    forEach:{
        value:function(f){
            for(var i=Math.ceil(this.from);i<this.to;i++){
                f(i);
            }
        }
    },
    toString:{
        value:function(){
            return '{from:'+this.from+',to:'+this.to+'}';
        }
    }
});
var rangeObj = new Range(3,8);
rangeObj.forEach(function(x){
    console.log(x);
});
console.log(rangeObj.toString())

在该例子中,我们定义了一个表示数字范围的类Range,这个类的实例化对象有两个属性,from,to,这是对象属性,这类 Range函数既可以当作工厂方法调用,可以以构造函数的方式调用,两种方式都会产生一样的效果我们把实例字段from,to的属性特性定义为{writable:false,configurable:false,enumerable:true},即,只读,可枚举(能通过ffor in循环遍历出来),不可配置(属性不能删除),这样可以增强实例字段的封装性。
然后在Range.prototype上定义实例方法,同时我们将实例方法设置为不可枚举(这正是我们所期望的),不可配置。这样当通过实例化这个类时,所产生的对象就是不可变的。
二、为Range类定义一个命名空间
我们可以用一个函数来当作命名空间,这样我们所定义的工具库就可以避免对命名空间的污染,防止命名冲突。

(function(){
    function Range(from,to){
    var props = {
        from:{value:from,writable:false,configurable:false,enumerable:true},
        to:{value:to,writable:false,configurable:false,enumerable:true}
    };
    if(this instanceof Range){
        Object.defineProperties(this,props);
    }
    else{
        return Object.create(Range.prototype,props);
    }
}
Object.defineProperties(Range.prototype,{
    includes:{ value:function(x){ return x>=this.from&&x<=this.to; }},
    forEach:{ value:function(f){ for(var i=Math.ceil(this.from);i<this.to;i++){ f(i); } } }, toString:{ value:function(){ return '{from:'+this.from+',to:'+this.to+'}'; } } }); return Range; }());

在这是,我们做一个匿名函数立即执行,使之产生一个私有的命名空间,在这个命名空间中,我们定义了一个Range类,要注意的是,在这个命名中定义的工具方法,在外部是不可见的,因此它并不会污染全局命名空间。当我们要导出一些公共的API供外部使用时,只需将里面的函数返回即可,如需返回多个API,可把这些API加到一个对象中一起返回。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值