zoukankan      html  css  js  c++  java
  • 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)//true
    160         alert(friend instanceof Object)//true
    161         alert(friend.constructor==Person);//false
    162         alert(friend.constructor==Object);//true
    163         //如果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);//true
    181 
    182         //这种手动的添加了constructor会使constructor变成可枚举的元(原生的constructor属性时不可枚举的)。
    183         //这种情况下就可以使用
    184         Object.defineProperty(Person.prototype,"constructor",{
    185             enumerable:false,
    186             value:Person
    187         });
    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);//function
    222         alert(typeof String.prototype.substring);//function
    223         //不仅可以在原生对象的原型取得虽有默认方法的引用,而且可以定义新的方法
    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>
  • 相关阅读:
    vue 基础
    Bootstrap 基础
    FormatMessage函数
    CreateProcess中的部分参数理解
    关于远程线程的调用
    利用服务枚举进程
    FindQQByProcess
    寻找kernel32.dll的地址
    ShellCode的几种调用方法
    操作系统版本
  • 原文地址:https://www.cnblogs.com/goesby/p/javascript.html
Copyright © 2011-2022 走看看