读书笔记----javascript类和模块

  1. 构造函数时用来初始化新创建的对象的,使用new关键字来初始化这个对象。使用new调用构造函数会自动创建一个新对象,因此构造函数本身只需要初始化这个新对象即可。
//range,js 实现一个能表示值的范围的类 
    function range(from,to){
     //使用inherit()创建对象,这个对象继承下面定义的原型对象
     var r=inherit(range.methods);//创建一个对象r,继承原型对象range.methods
     //定义起始位置和结束为止,这两个属性是非共享的不可继承的,每个对象都拥有唯一的属性
      r.from=from;
      r.to=to;
      return r;//返回创建的新对象   

        }

    //原型对象的定义方法,这些方法为每个范围对象继承
    range.methods={
        includes:function (x){
            return this.from<=x&&x<=this.to;

            },
            //对于范围内的每个整数都调用一次f
            foreach: function (f){
                for (var x=Math.ceil(this.from);x<=this.to;x++) f(x);

                },
                //返回表示这个范围的字符串
                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)
        // form to都是非共享的,不可继承的,但是range.methods中定义的可共享的,可继承的方法
        //都用到了from和to,而且使用了this关键字。任何类的方法都可以通过this读取对象的属性
这里写代码片
  1. 调用构造函数,构造函数的prototype属性被用做新对象的原型。所以通过构造函数创建的对象都继承一个相同的对象,他们都是同一个类的成员。
//使用构造函数定义范围类
            function Range(from,to){  //定义构造函数就是定义类,并且类的首字母大写
                this.from=from;
                this.to=to;
                }
            Range.prototype={  //Range()构造函数调用会自动使用Range.prototype作为新的Range对象原形
                includes:function (x){return this.from<=x&&x<=this.to;},
                foreach:function(f){
                    for (var x=Math.ceil(this.from);x<=this.to;x++) f(x);
                    },
                    toString: function(){return "("+this.from+"..."+this.to+")";}
                };
            var r=range(1,3);
            r.includes(2);
            r.foreach(console.log);
            console.log(r);

        //上述构造函数定义类,定义的Range类使用它自身的一个对象重写预定义的Range.prototype对象。
        //这个心定义的原型对象不含有constructor属性,因此Range类实例也不含有constructor属性
  1. 原型对象是类的唯一标识,当且仅当两个对象继承同一个原型对象是,它们才是同一个类的实例。
    r instanceof Range//如果r继承自Range.prototype,则返回true
    instanceof运算符并不会检查r是否由Range构造函数初始化来的,只会检查r是否继承自Range.prototype
  2. 每个javscript函数都拥有一个prototype属性,这个属性的值是一个对象,这个对象包含唯一一个不可枚举的属性constructor.
//显式给原型添加一个构造函数
        Range.prototype={
            constructor:Range, // 显式设置构造函数反向引用
            includes: function(x){ return this.from<=x&&x<=this.to;},
            foreach:function (f){
                for (var x=Math.ceil(this.from);x<=this.to;x++) f(x);
                },
                toString: function(){  return "("+this.from+"..."+this.to+")";}
            };

var p=F.prototype;//这是F相关联的原型对象
var c=p.constructor;//这是与原型相关联的函数
c===F //true 对于任意函数F.prototype.constructor==F
对象继承的constructor均指代它们的构造函数
var 0=new F();//提供F的一个对象
o.constructor===F //true constructor属性指代这个类

    //使用预定义的原型对象,预定义的原型对象包含constructor属性,然后依次给原型对象添加方法
            //扩展预定义的Range.prototype对象,这样就自动创建Range.prototype.constructor属性
            Range.prototype.includes=function (x){ return this.from<=x&&x<=this.to;};
            Range.prototype.foreach=function (f){
                for (var x=Math.ceil(this.from);x<=this.to;x++) f(x);
                };
            Range.prototype.toString=function(){
                return "("+this.from+"..."+this.to+")";
                };
  1. 构造函数对象:为javascript的类定义了名字,任何添加到这个构造函数对象中的属性都是类字段和类方法
    原型对象:属性被类的所有实例所继承,如果原型对象的属性值是函数的话,这个函数就作为类的实例方法来调用
    实例对象:类的每个实例都是一个独立的对象
  2. 定义类的步骤:第一步先定义一个构造函数,并设置初始化新对象的实例属性
    第二步给构造函数prototype对象定义实例方法
    第三步给构造函数定义类字段和类属性
    //定义一个简单的类函数
    function defineClass( constructor,  //用来设置实例属性的函数
                          methods,     //实例的方法,复制至原型中
                          statics    //类属性,复制到构造函数中                      
                         )
    {  if (methods) extend(constructor.prototype,methods);
        if (statics) extend(constructor,statics);
        return constructor;

        }
    //Range 类的实现
    var SimpleRange=
        defineClass (function (f,t) {this.f=f;this.t=t;},
                               {
                                   includes:function (x){return this.f<=x&&x<=this.t;},
                                   toString: function(){  return this.f+"..."+this.t}
                                   },
                                 {upto: function(t) {return new SimpleRange(0,t);}}
                               );
  1. js中的原型继承机制是动态的,对象从原型继承属性,如果创建对象之后原型的属性发生改变,也会影响到继承这个原型的所有实例对象。
  2. 检测对象类的技术 instanceof isPrototypeOf constructor
    instanceof检测对象继承关系,而不是检测创建对象的构造函数
    isPrototypeOf()检测对象原型链上是否存在某个特定的原型对象
    这两种方法的缺点:无法通过对象获得类名,只能检测对象是否属于指定的类名。在多个执行上下文中存在构造函数的多个副本的时候,检测结果出错。
  3. 辅助构造函数
//辅助构造函数
    function SetFromArray(a){
        //将a的元素作为参数传入
        Set.apply(this,a);
        }
    //设置原型,以便SetFormArray能够创建Set实例
    SetFromArray.prototype=Set.prototype;
    var s=new SetFromArray([1,2,3]);
     s instanceof Set  //true
  1. 如果O是类B的实例,B是A 的子类,那么O一定从A中继承了属性。为此首先确保B的原型对象继承自A的原型对象
    B.prototype=inherit(A.prototype); //子类派生自父类
    B.prototype.constructor=B; //重载继承来的constructor属性
    这是创建子类的关键,如果不这样做,原型对象仅仅是一个普通对象,它只继承Object.prototype。
  2. Object.preventExtensions()可以将对象设置为不可扩展的,不能为对象添加新的属性
  3. Object.seal()除了阻止用户给对象添加新属性,还能将当前已有的属性设置为不可配置。
//定义一个复数类
        function Complex(real,imaginary){
            if (isNaN(real)||isNaN(imaginary))
            throw new TypeError();
            this.r=real;
            this.i=imaginary;
            }
        Complex.prototype.add=function(that){
            return new Complex(this.r+that.r,this.i+that.i);
            }
        Complex.prototype.equals=function(that){
            return that!=null&&  //必须有定义且不能是null
            that.constructor===Complex&&  //必须是Complex实例
            this.r===that.r&&this.i===that.i;  //包含相同的值

            }
            //定义对复数运算有帮助的类字段,他们都是常量
            Complex.ZERO=new Complex(0,0);
            Complex.ONE=new Complex(1,0);
function typeAndValue(x){
            if (x==null)  return " "// null undefined 没有构造函数
            switch (x.constructor){
                case Number: return "Number:"+x;//处理原始类型
                case String: return "String:' "+x+" '" ;
                case Date:return "Date: "+x;  //处理内置对象
                case RegExp: return "Regexp: "+x;
                case Complex:return "Complex: "+x;//定义自定义类型
                }
            }
            //case后的表达式都是函数,如果改为typeof 运算符或获取到对象的class属性的话,应当改为字符串
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值