zoukankan      html  css  js  c++  java
  • 面向对象与原型(二)

    原型

    我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个对象。使用原型的好处可以让所有对象实例共享它所包含的属性和方法。不必再构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。

    function Box(){}             //创建一个构造函数
    
    Box.prototype.name = 'Lee';                            //在原型里
    Box.prototype.age = 100;
    Box.prototype.run = function(){                         //在原型里添加方法
          return this.name + this.age + '运行中...';   
    }

    原型声明方式 图:

    实例化方法:不同的实例它们的地址是不一样的,是唯一的。

    原型方法:对象里的原型地址共享的,大家都一样。

      在原型模式声明中,多了两个属性,这两个属性都是创建对象是自动生成的。

       __proto__

      属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性constructor。

      constructor

    1、构造属性,可以获取构造函数本身

    2、作用是被原型指针定位,然后得到构造函数本身

    3、其实就是用来让对象实例对应原型对象的

     

     

    ps:IE浏览器在脚本访问—__proto__会不能识别。
     
    问:判断一个对象实例(对象引用)是不是指向原型对象?
    答:Object.prototype.isPrototype(obj)
    ps:只要实例化对象,都会自动指向原型
     
    问:如何判断属性是在构造函数的实例里,还是在原型里?
    答:
    box.hasOwnProperty('name');         //判断构造函数的实例中是否存在指定属性
    alert('name' in box);              //返回true or false 无论在实例中还是原型中,只要存在指定属性,就返回true
    function isProperty(object,propety){        //构造函数名,属性名
        return !object.hasOwnProperty(property) && (propety in object);
    }

    字面量方式创建原型

    function Box(){}
    
    Box.prototype = {
           name:'Lee',
           age:100,
           run:function(){
                return this.name + this.age + '运行中...';
           } 
    }    

     ps:字面量创建原型对象,使用constructor属性不会指向构造函数,而会指向object。

    因为Box.prototype={};这种写法其实就是创建了一个新对象。而每创建一个函数,就会同时创建它prototype,这个对象也会自动获取constructor 属性。所以,新对象的constructor 重写了Box 原来的constructor,因此会指向新对象,那个新对象没有指定构造函数,那么就默认为Object。

     
     问:如何让字面量方式的constructor指向构造函数呢?
    答:
    Box.prototype={
        constructor:Box        //强制指向构造函数
    }

    ps:重写会切断之前的原型。所以在声明前就要指向构造函数。

    拓展:

    原型对象不仅仅可以在自定义对象的情况下使用,而ECMAScript 内置的引用类型都可以使用这种方式,并且内置的引用类型本身也使用了原型。
    alert(Array.prototype.sort);                       //sort 就是Array 类型的原型方法
    alert(String.prototype.substring);                   //substring 就是String 类型的原型方法
    String.prototype.addstring = function () {                //给String 类型添加一个方法
    return this + ',被添加了!';                               //this 代表调用的字符串
    };
    alert('Lee'.addstring());                                 //使用这个方法
     

    原型的缺点:

    1、初始化不能传参
    2、在第一个实例修改后, 保持了共享
     
    解决方法:组合构造函数+原型模式
    function Box(name,age){                                          //将所有信息封装到函数体内
          this.name = name;
          this.age = age;
          if(typeof this.run != 'function'){                         //仅在第一次调用的初始化
             Box.prototype.run = function(){
                   return this.name+ this.age+'运行中...';
              }
          }
    }

    当第一次调用构造函数时,run()方法发现不存在,然后初始化原型。当第二次调用,就不会初始化,并且第二次创建新对象,原型也不会再初始化了。这样及得到了封装,有实现了原型方法共享,并且属性都保持独立。

    ps:使用动态原型模式,要注意一点,不可以在使用字面量的方法重写原型,因为会切断实例和新原型之间的联系。


  • 相关阅读:
    (二)扩展原理:【2】BeanDefinitionRegistryPostProcessor
    寒假学习日报3
    寒假学习日报6
    寒假学习日报8
    寒假学习日报9
    寒假学习日报7
    寒假学习日报1
    寒假学习日报4
    构建之法阅读笔记1
    寒假学习日报2
  • 原文地址:https://www.cnblogs.com/hynb/p/5831938.html
Copyright © 2011-2022 走看看