类、构造函数、原型
构造函数
       new操作符用来生成一个新的对象,new后面必须要跟上一个函数,也就是我们常说的构造函数,构造函数的工作原理又是怎样的呢?
       先看一个例子:
       JS代码:(见附件test1.html)
       function Person(name,sex){
              this.name = name;
              this.sex = sex;
       }
 
       var per = new Person("wangsy","male");
       alert("name:" + per.name + "_sex:" + per.sex);
 
       下面说明一下这个工作的步骤:
       开始创建了一个函数(不是方法,只是一个普通的函数),注意用到了this关键字,也就是说通过对象调用方法的时候,this关键字会指向该对象(不使用对象直接调用该函数则this指向整个的script域,或者函数所在的域)。当我们使用new操作符时,js会先创建一个空的对象,然后这个对象被new后面的方法的this关键字引用!确定如果的方法中通过操作this就给这个新创建的对象相应的赋予了属性,最后返回这个经过处理的对象。这样上面的例子就很清楚:先创建一个空对象,然后调用person方法对其进行赋值,最后返回该对象,我们就得到了一个per对象。
       js中,每个对象都有一个prototype属性,这个属性指向了一个prototype对象。
       上面我们提到了用new来创建一个对象的过程,事实上在这个过程中,当创建了空对象后,new会接着操作刚生成的这个对象的prototype属性。
       每个方法都有一个prototype属性(因为方法本身也是对象)new操作符生成的新对象的prototype属性值和构造方法的prototype属性值是一致的。构造方法的prototype属性指向了一个prototype对象,这个prototype对象初始只有一个属性constructor,而这个constructor属性又指向了prototype属性所在的方法。
       这样,当用构造函数创建一个新的对象时,它会获取构造函数的prototype属性所指向的prototype对象的所有属性,对构造函数对应的prototype对象所做的任何操作都会反应到它所生成的对象身上,所有的这些对象共享构造函数对应的prototype对象的属性(包括方法)。具体例子:
JS代码:(见附件test2.html)
//构造函数
function Person(name,sex){
       this.name = name;
       this.sex = sex;
}
 
//prototype属性对应的prototype对象的属性赋值
Person.prototype.age = 12;
//添加方法
Person.prototype.print = function(){
       alert(this.name + "_" + this.sex + "_" + this.age);
}
 
var p1 = new Person("name1","male");
var p2 = new Person("name2","male");
//name1_male_12
p1.print();
//name2_male_12
p2.print();
 
//改变prototype对象的属性值,注意是操作构造函数的prototype属性
Person.prototype.age = 18;
//name1_male_18
p1.print();
//name2_male_18
p2.print();
 
       改变对象的prototype属性和prototype属性的注意事项:给出一种不是很恰当的解释,或许有助于我们理解,当我们new了一个对象之后,这个对象就会获得构造函数的prototype属性(包括函数和变量),可以认为是构造函数()继承了它的prototype属性对应的prototype对象的函数和变量,也就是说,prototype对象模拟了一个超类的效果,听着比较拗口,看个实例:
JS代码:(见附件test3.html)
//Person类的构造函数
function Person(name,sex){
       this.name = name;
       this.sex = name;
}
 
//Person类的prototype属性对应的prototype对象的属性赋值
//相当于为Person类的父类添加属性
//Person类的父类添加方法
Person.prototype.print = function(){
       alert(this.name + "_" + this.sex + "_" + this.age);
}
 
//p1age属性继承了Person类的父类(prototype对象)
var p1 = new Person("name1","male");
var p2 = new Person("name2","male");
 
//name1_male_12
p1.print();
//name2_male_12
p2.print();
 
//改变p1实例的age
p1.age = 34;
//name1_male_34
p1.print();
//name2_male_12
p2.print();
 
//改变Person类的超类的age属性
Person.prototype.age = 22;
//p1age属性并没有随着prototype属性的改变而改变
p1.print();
//p2的属性发生了变化
p2.print();
 
//改变p1对象的print方法
p1.print = function(){
       alert("I am p1");
}
 
//p1的方法发生了改变
p1.print();
//p2的方法并没有改变
p2.print();
//改变Person超类的print方法
Person.prototype.print = function(){
       alert("new print method");
}
 
//p1print方法仍旧是自己的方法
p1.print();
//p2print方法随着超类方法的改变而改变
p2.print();