类、构造函数、原型
构造函数
       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);
}

 

//p1 age 属性继承了 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;
//p1 age 属性并没有随着 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");
}

 

//p1 print 方法仍旧是自己的方法
p1.print();
//p2 print 方法随着超类方法的改变而改变
p2.print();