首页 > 代码库 > javascript——面向对象程序设计(2)

javascript——面向对象程序设计(2)

  1 <script type="text/javascript">  2         //1、理解原型对象  3         //2、原型与in操作符  4         //3、更简单的原型语法  5         //4、原型的动态性  6         //5、原生对象原型  7         //6、原型对象的问题  8   9         //1、无论什么时候,只要创建了一个函数,就会根据一组特定的规则,为该函数创建一个prototype属性,该属性指向函数的原型对象 10         //在默认情况下,所有的原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针 11         // 12         function Person(){ 13  14         } 15         //Person.prototype.constructor 指向Person 16         //创建了自定义的构造函数之后,其原型对象默认只会取得constructor属性,至于其他方法则都是从Object继承而来 17         //当调用函数的创建一个新实例之后,该实例的内部包含一个指针(内部属性)指向构造函数的原型对象 18         //在Firefox、safari、chrome在每个对象上都支持一个属性_proto_访问 19         var p1=new Person(); 20         alert(Person.prototype.isPrototypeOf(p1)) 21  22         alert(Object.getPrototypeOf(p1)==Person.prototype) 23  24         //虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们在实例中添加了一个属性 25         //而该属性的名称与原型的中的实例同名,那我们就在实例中创建该属性,该属性将会屏蔽原型中的那个属性。eg: 26         function Person() { 27         } 28         Person.prototype.name="amber"; 29         Person.prototype.age=23; 30         Person.prototype.job="software engineer"; 31         Person.prototype.sayName=function(){ 32             alert(this.name) 33         } 34  35         var person1=new Person(); 36         var person2=new Person(); 37         person1.name="amber.Xu"; 38         alert(person1.name);//amber.xu --来自实例 39         alert(person2.name);//amber --来自原型 40  41         delete  person1.name; 42         alert(person1.name);//amber --来自原型 43  44         //使用hasOwnProperty()方法可以检测一个属性是存在于实例中还是存在于原型中,这个方法(从Object继承而来) 45         //只在给定属性存在于对象实例中时,才会返回true 46         function Person() { 47         } 48         Person.prototype.name="amber"; 49         Person.prototype.age=23; 50         Person.prototype.job="software engineer"; 51         Person.prototype.sayName=function(){ 52             alert(this.name) 53         } 54         var person1=new Person(); 55         var person2=new Person(); 56  57         alert(person1.hasOwnProperty("name"));//false 来自实例 58  59         alert(person2.hasOwnProperty("name"));//false 来自实例 60  61         person1.name="amber.xu"; 62         alert(person1.name); 63         alert(person1.hasOwnProperty("name"));//true 来自实例 64  65         delete person1.name; 66         alert(person1.name); 67         alert(person1.hasOwnProperty("name"));//false 来自原型 68  69  70  71         //2、原型与in操作符 72         //in 有两种使用方式,一个是的单独使用和在for-in 中使用。在单独使用时,in操作符会在对象能够访问给定属性时返回true 73         //无论该属性时来自原型还是实例 74         function Person() { 75         } 76         Person.prototype.name="amber"; 77         Person.prototype.age=23; 78         Person.prototype.job="software engineer"; 79         Person.prototype.sayName=function(){ 80             alert(this.name) 81         } 82         var person1=new Person(); 83         var person2=new Person(); 84         alert("name"  in person1);//true 来自原型 85         alert("name"  in person2);//true 来自原型 86         alert("height"  in person1);//false 87  88  89         //这样就可以封装一个函数(给定属性是否是来给定对象的原型) 90         function hasPrototypeProperty(object,name){ 91             return !object.hasOwnProperty(name) && (name in object); 92         } 93         alert("----------------------------------"); 94         alert(hasPrototypeProperty(person1,"name"));//true 95  96         person1.name="张三"; 97         alert(hasPrototypeProperty(person1,"name"));//false 98  99 100         //使用for-in 返回的是所有能够通过对象访问、可枚举的属性,其中既包含原型属性也包含实例属性。101         //屏蔽了原型中不可枚举属性(将Enumerable标记为false的属性)的实例属性也会在for-in中返回102         //ie早期版本总中有一个bug:屏蔽了原型中不可枚举属性的实例属性也不会在for-in中返回103         //eg:104         var o={105             toString:function(){106                 return "my object";107             }108         };109 110         for(var prop in o){111             if(prop=="toString"){112                 alert("找到了");//在ie早期版本中不会显示113             }114         }115 116         //要取得对象上所有可枚举的属性,可以使用ECMAScript5的Object.keys()方法。接受一个对象作为参数,117         //包含所有可枚举属性的字符串数组118         function Person() {119         }120         Person.prototype.name="amber";121         Person.prototype.age=23;122         Person.prototype.job="software engineer";123         Person.prototype.sayName=function(){124             alert(this.name)125         }126         var person1=new Person();127         var person2=new Person();128         var  keys=Object.keys(Person.prototype);129         alert(keys)130 131         person1.name="amber.Xu";132         person1.age=23;133         var keys=Object.keys(person1);134         alert(keys)135 136         alert("-----------------------------------------")137         //如果想要得到所有的实例属性不管他是否可以枚举,都可以使用138         alert(Object.getOwnPropertyNames(person1));139         alert(Object.getOwnPropertyNames(Person.prototype));140 141         alert("更简单的原型语法-----------------------------------------")142         //3、更简单的原型语法143         function Person() {144 145         }146 147         Person.prototype={148             name:"AMBER",149             age:23,150             job:"software",151             sayName:function(){152                 alert(this.name)153             }154         }155 156         //这样写之后constructor属性不再指向Person函数,而是指向Object构造函数。157         //尽管通过instanceof操作符还能返回正确的结果,但是通过constructor已经无法确定对象的类型了,eg:158         var friend=new Person();159         alert(friend instanceof Person)//true160         alert(friend instanceof Object)//true161         alert(friend.constructor==Person);//false162         alert(friend.constructor==Object);//true163         //如果constructor对你真的很重要,可以向下面一样设置成适当的值164 165         function Person() {166 167         }168 169         Person.prototype={170             constructor:Person,171             name:"AMBER",172             age:23,173             job:"software",174             sayName:function(){175                 alert(this.name)176             }177         }178         var friend=new Person();179         alert("手动设置constructor-----------------------------------------")180         alert(friend.constructor==Person);//true181 182         //这种手动的添加了constructor会使constructor变成可枚举的元(原生的constructor属性时不可枚举的)。183         //这种情况下就可以使用184         Object.defineProperty(Person.prototype,"constructor",{185             enumerable:false,186             value:Person187         });188 189 190         //原型的动态性191         var friend=new Person();192         Person.prototype.sayHi=function(){193             alert("Hi");194         }195 196         friend.sayHi();//Hi (正常执行)197         //因为实例和原型之间是松散的连接关系,实例与原型之间的连接只不过是一个指针,而非副本198         //当我们调用sayHi()方法时,首先会在实例中搜索名为sayHi的方法,在没找到的情况下会搜索原型。199 200         //但是,如果是重写整个原型对象,那么情况就不一样了。201         //我们知道,调用构造函数时会为实例添加一个指向最初原型的Prototype指针,而把原型修改为另一个对象就等于切断了构造函数与最初原型之间的联系。202         //请记住:实例中的指针仅指向原型,而不指向构造函数。eg:203         function A(){}204         var a1=new A();205         A.prototype={206             constructor:A,207             name:"AMBER",208             age:23,209             job:"software",210             sayName:function(){211                 alert(this.name)212             }213         }214         alert("ERROR-------------------------------------");215         alert(a1.sayName());216         //我们创建了一个A的实例,然后又重写了其原型对象,然后在调用a1.sayName()发生了错误,因为a指向的原型中不包含以该名字命名的属性/方法217 218         //原生对象的原型219         //原型模式的重要性不仅体现在创建自定义类型方面。就连所有的原生的引用类型,都是采用这种模式创建的。所有的原生引用类型220         //都在其构造函数的原型上定义的方法 eg:221         alert(typeof Array.prototype.sort);//function222         alert(typeof String.prototype.substring);//function223         //不仅可以在原生对象的原型取得虽有默认方法的引用,而且可以定义新的方法224         //为String类型添加一个startsWith()的方法225         String.prototype.startsWith=function(text){226             return this.indexOf(text) == 0;227         };228         var msg="Hello";229         alert(msg.startsWith("H"));230 231         //我们并不建议这样做。232 233         alert("原型对象的问题");234         //6、原型对象的问题  实例235         function Ques() {236         }237 238         Ques.prototype={239             constructor:Ques,240             name:"amber",241             age:23,242             job:"IT",243             friends:["张三","李四"],//引用类型244             sayName:function(){245                 alert(this.name)246             }247         };248 249         var q1=new Ques();250         var q2=new Ques();251         q1.friends.push("王五");252         alert(q1.friends);//253         alert(q2.friends);//254         alert(q1.friends===q2.friends);255     //相信大家已经看到了问题,当我创建了两个实例q1、q2,当我为q1的“朋友”添加了“王五”之后,q2的”朋友“也有了三个张三、李四、王五256     //那是因为数组存在于Ques.prototype上,而非q1上。所以出现了如上结果。257 258     //而正是这个问题,我们很少看到有人单独使用原型模式的原因所在。259     </script>

 

javascript——面向对象程序设计(2)