<html> <head> <script type="text/javascript"> //函数的prototype属性 //每一个函数都包含了一个prototype(原型)属性,这个属性构成了javascript面向对象的核心基础 //构造函数:new操作符用来生成一个新的对象.new后面必须要跟上一个函数,也就是我们常说的构造函数. function Person(name,sex) { this.name = name; this.sex = sex; } function test1() { var per=new Person("latty","male"); alert("name:"+per.name+",_sex:"+per.sex); } //工作步骤如下: //1.开始创建了一个函数(不是方法,只是一个普通的函数),这里this关键字表示调用该方法的对象 //通过对象调用"方法"的时候,this关键字会指向该对象(不使用对象直接调用该函数则this指向整个的script域,或者函数所在的域 //2.我们使用new操作符时,javascript会先创建一个空的对象,然后这个对象被new后面的方法(函数)的this关键字引用!然后在方法中 //通过操作this,就给这个新创建的对象相应的赋予了属性 //prototype(原型)-- //在javascript中,每个对象都有一个prototype属性,这个属性指向了一个prototype对象. //用new来创建一个对象的过程,当创建了空对象后,new会接着操作刚生成的这个对象的prototype属性. //每个方法都有一个prototype属性(因为方法本身也是对象),new操作符生成的新对象的prototype属性值和构造方法的prototype属性值是一致的. //构造方法的prototype属性指向了一个prototype对象,这个prototype对象初始只有一个属性constructor,而这个constructor属性又指向了prototype属性所在的方 //法 //当用构造函数创建一个新的对象时,它会获取构造函数的prototype属性所指向的prototype对象的所有属性.对构造函数对应的prototype对象 //所做的任何操作都会反应到它所生成的对象身上,所有的这些对象共享构造函数对应的prototype对象的属性(包括方法 function test2() { Person.prototype.age=12; //为prototype属性对应的prototype对象的属性赋值 Person.prototype.print=function()//添加方法 { alert(this.name+"_"+this.sex+"_"+this.age); }; var p1 = new Person("name1","male"); var p2 = new Person("name2","male"); p1.print(); //name1_male_12 p2.print(); //name2_male_12 Person.prototype.age = 18; //改变prototype对象的属性值,注意是操作构造函数的prototype属性 p1.print(); //name1_male_18 p2.print(); //name2_male_18 } //当我们new了一个对象之后,这个对象就会获得构造函数的prototype属性(包括函数和变量), //可以认为是构造函数(类)继承了它的prototype属性对应的prototype对象的函数和变量 function test3() { Person.prototype.age = 12; //为Person类的prototype属性对应的prototype对象的属性赋值, //相当于为Person类的父类添加属性 Person.prototype.print = function() { //为Person类的父类添加方法 alert(this.name+"_"+this.sex+"_"+this.age); }; var p1 = new Person("name1","male"); //p1的age属性继承子Person类的父类(即prototype对象) var p2 = new Person("name2","male"); p1.print(); //name1_male_12 p2.print(); //name2_male_12 p1.age = 34; //改变p1实例的age属性 p1.print(); //name1_male_34 p2.print(); //name2_male_12 Person.prototype.age = 22; //改变Person类的超类的age属性 p1.print(); //name1_male_34(p1的age属性并没有随着prototype属性的改变而改变) p2.print(); //name2_male_22(p2的age属性发生了改变) delete p1.age //删除子类与父类同名的属性,从父类那里继承过来的属性就被暴露出来了! p1.print(); //name1_male_12!!!!!!! p2.print(); //name2_male_12 p1.print = function() { //改变p1对象的print方法 alert("i am p1"); } p1.print(); //i am p1(p1的方法发生了改变) p2.print(); //name2_male_22(p2的方法并没有改变) Person.prototype.print = function() { //改变Person超类的print方法 alert("new print method!"); } p1.print(); //i am p1(p1的print方法仍旧是自己的方法) p2.print(); //new print method!(p2的print方法已经改变 } //由上面可以看出prototype属性在javascript中模拟了父类(超类)的角色 //当我们对这些实例对象的属性和方法重新赋值或定义后,那么实例对象的属性或方法就不再指向类的prototype属性中定义的属性和方法 //在javascript中,所有的方法都有一个call方法和apply方法.这两个方法可以模拟对象调用方法.它的第一个参数是对象,后面的 //参数表示对象调用这个方法时的参数 function test4() { var o = new Object(); //空对象 alert(o.name + "_" + o.sex); //undefined_undefined Person.call(o,"sdcyst",1); //相当于调用:o.Person("sdcyst",1) alert(o.name + "_" + o.sex); //sdcyst_1 Person.apply(o,["name",0]);//apply方法作用同call,不同之处在于传递参数的形式是用数组来传递 alert(o.name + "_" + o.sex); //name_0 //实例变量和实例方法都是通过实例对象加"."操作符然后跟上属性名或方法名来访问的 //这样就可以直接用类名加"."操作符然后跟上属性名或方法名来访问. } </script> </head> <body> <input type="button" value="test1" onclick="test1();"/><br/> <input type="button" value="test2" onclick="test2();"/><br/> <input type="button" value="test3" onclick="test3();"/><br/> <input type="button" value="test4" onclick="test4();"/><br/> </body> </html>