首页 > 代码库 > Javascript类和模块(一)

Javascript类和模块(一)

  1. 原型对象是类的唯一标识:当且仅当两个对象继承自同一个原型对象时,它们才是属于同一个类的实例。而初始化对象的状态的构造函数则不能作为类的标识,两个构造函数的prototype属性可能指向同一个原型对象。那么这两个构造函数创建的实例是属于同一个类的。

  2. 一个典型的面向对象的js程序:

functionRange(from,to){

     this.from=from;

     this.to=to;

    }

    Range.prototype={

     includes:function(x){

               return this.from<=x&&x<=this.to;

     },

     foreach:function(f){

               for(varx=Math.ceil(this.from);x<this.to;x++){

                        f.log(x);

               }

     },

     toString:function(){

               return"("+this.from+"..."+this.to+")";

     }

}

//用例

var r=new Range(1,3);

console.log(r.includes(2));

r.foreach(console);

console.log(r.toString());

  1. 代码规范:类(构造函数)首字母大写,(普通)方法首字母小写

  2. 实际上instanceof运算符并不会检查r是否是由Range()构造函数而来,而会检查是否继承自Range.prototype。不过,instanceof的语法则强化了“构造函数是类的公有标识”的概念。

  3. constructor属性:实例,

varF=function(){

}

varp=F.prototype;//这是F相关联的原型对象

var c=p.constructor;//这是与原型相关联的函数

console.log(p);//函数的原型是对象Object{}

console.log(c);//p的构造函数是构造函数function(){}

可以看到构造函数的原型中存在预先定义好的constructor属性,这意味着对象通常继承的constructor均指代它们的构造函数。由于构造函数是“公共标识”,因此这个constructor属性为对象提供了类。

var o=new F(); //创建类F的一个对象

o.constructor===F;//true,constructor属性指代这个类

构造函数和原型对象之间的关系如下图:

wKioL1RKY_agOF9XAAChuvOZwLU928.jpg

需要注意的是2中定义的Range类使用它自身的一个对象重写预定义的Range.prototype对象。这个新定义的原型对象不含有constructor属性。如下图:

wKiom1RKY6ahY7iMAAGtb3yXH-I011.jpg

wKioL1RKY_bhyt0cAAHT2E2YdNY619.jpg

因此Range类的实例也不含有constructor属性。我们可以通过补救措施来修正这个问题,显示给原型添加一个构造函数。

Range.prototype={

constructor:Range,

includes:function(x){

           returnthis.from<=x&&x<=this.to;

},

foreach:function(f){

           for(varx=Math.ceil(this.from);x<this.to;x++){

                    f.log(x);

           }

},

toString:function(){

           return"("+this.from+"..."+this.to+")";

}

}

另一种常见的解决方法是使用预定义的原型对象,预定义的原型对象包含constructor属性,然后依次给原型对象添加方法

Range.prototype.includes=function(x){returnthis.from<=x&&x<=this.to;};

Range.prototype.foreach=function(f){for(var x=Math.ceil(this.from);x<this.to;x++){f.log(x);};

Range.prototype.toString=function(){return"("+this.from+"..."+this.to+")";};

  1. Javascript中类继承:构造函数对象,任何添加到这个构造函数对象中的属性都是类字段和类方法(如果属性值是函数的话就是类方法);原型对象,原型对象的属性被类的所有实例所继承,如果原型对象的属性值是函数的话,这个函数就作为类的实例的方法来调用;实例对象,类的每个实例都是一个独立的对象,直接给这个实例定义的属性是不会为所有实例对象共享的。定义在实例上的非函数属性,实际上是实例的字段。

  2. javascript中定义类的步骤可以缩减为三步:1)先定义一个构造函数,并设置初始化新对象的实例属性。2)给构造函数的prototy对象定义实例的方法;3)给构造函数定义类字段和类属性,下面是一段模拟java中类的定义的js代码:

/**

 * 复数的构造函数,这个构造函数为它所创建的每个实例定义实例字段ri

 * @param {[type]} real      [实部]

 * @param {[type]} imaginary [虚部]

 */

functionComplex(real,imaginary){

    if(isNaN(real)||isNaN(imaginary)){

               throw new TypeError(‘传入参数类型错误!‘);

    }

    this.r=real;

    this.i=imaginary;

}

/**

 * 复数加法,类的实例方法定义为原型对象的函数值属性

 * 这里定义的方法可以被所有实例继承,并为他们提供共享行为

 * 需要注意的是,Javascript的实例化方法必须使用关键字this来存取实例的字段

 * @param {[type]} c [description]

 */

Complex.prototype.add=function(c){

    return new Complex(this.r+c.r,this.i+c.i);

}

//这里定义了一些复数运算有帮助的类字段

Complex.ZERO=new Complex(0,0);

8.       编码规范:1)以大写字母命名的成员是不能修改的;2)以下划线为前缀的命名在类外不可见

9.Javascript中基于原型的继承机制是动态的:对象从其原型继承属性,如果创建对象之后原型的属性发生改变,也会影响到继承这个原型的所有实例对象。


本文出自 “虎哥的博客” 博客,请务必保留此出处http://7613577.blog.51cto.com/7603577/1567787

Javascript类和模块(一)