• 精读《javascript高级程序设计》笔记三——面向对象的程序设计


    重点来了,我认为这一章值得好好地反复地看。看第一遍 还是懵懵懂懂,现在看第二遍,终于能看出点意思了。

    创建对象

    1. 工厂模式
      function createPerson(name, age, job){
          var o = new Object();
          o.name = name;
          o.age = age;
          o.job = job;
          o.sayName = function(){
              alert(this.name);
          };
          return o;
      }
      
      var person1 = createPerson("Nicholas", 29, "Software Engineer");
      var person2 = createPerson("Greg", 27, "Doctor");
                      

      优点:解决了Object构造函数或对象字面量创建多个对象代码重复的问题

      缺点:无法识别对象.

    2. 构造函数模式:
      function Person(name, age, job){
          this.name = name;
          this.age = age;
          this.job = job;
          this.sayName = function(){
              alert(this.name);
          };
      }
      var person1 = new Person("Nicholas", 29, "Software Engineer");
      alert(person1.constructor == Person);
      alert(person1 instanceof Object);
      alert(person1 instanceof Person);
                      

      优点:可以将它的实例识别为一种特定的对象

      缺点:每个方法都要在每个实例上重新创建一遍,增加不必要的内存开支

    3. 原型模式
      function Person(){
      }
      Person.prototype.name = "Nicholas";
      Person.prototype.age = 29;
      Person.prototype.job = "Software Engineer";
      Person.prototype.sayName = function(){
          alert(this.name);
      };
      var person1 = new Person();
      person1.sayName();
      
      var person2 = new Person();
      person2.sayName();
      alert(person1.sayName === person2.sayName);
                      

      原型模式创建的属性对象是由所有实例共享的。

      缺点:原型模式在包含引用类型时,实例共享会引起比较严重的问题。

      在所有实现中都无法直接访问到prototype,只通通过isPrototypeOf()来检验对象之间是否存在这种关系。例:Person.prototype.isPrototypeOf(person1)

      在实例中添加一个与原型中的同名属性,会在实例中创建该属性,而不会改变原型的值

      var person1 = new Person();
      var person2 = new Person();
      person1.name = "Greg";
      alert(person1.name);   //"Greg"——来自实例
      alert(person2.name);   //"Nicholas"——来自原型
                      

      hasOwnProperty()检测一个属性是否在实例中;in 检测是否能访问到访属性,可能是在实例中,也可能是在原型中;

      /*检测属性是否存在于原型中*/
      function hasPrototypeProperty(object, name){
      	return !object.hasOwnProperty(name) && (name in object);
      }
                      

      更简单的原型:

      function Person(){
      }
      Person.prototype = {
          constructor : Person,  
          /*用字面量定义prototype时,要设置它的constructor,不然它的constructor会指向Object*/
          name : "Nicholas",
          age : 29,
          job : "Software Engineer",
          sayName : function (){
              alert(this.name);
          }
      };
      /*这样设置有一点不足,会使constructor变为可枚举的,如果是支持ECMAScript5的浏览器,可用Object.defineProperty()是方法来设置constructor*/    
      /*Object.defineProperty(Person.prototype, "constructor",{
          enumerable:false,
          value:Person
      });*/            
                      

      实例中的指针仅指向原型,而不指向构造函数

    4. 组合使用构造函数模式和原型模式

      构造函数模式用于定义实例属性,原型模式用于定义方法和共享属性。

      function Person(name,age,job){
          this.name = name;
          this.age = age;
          this.job = job;
          this.friends = ["Shelby","Court"];
      }
      
      Person.prototype = {
          constructor : Person,
          sayName : function(){
              alert(this.name);
          }
      }
                      
    5. 动态原型模式

      把所有信息封装到构造函数中,在构造函数中初始化原型。

      优点:解决了独立的构造函数模式和原型模式独立的问题,又同时保持了两者的优点。

      使用这种方法创建对象,不能用对象字面量重字原型。

      function Person(name, age, job){
          this.name = name;
          this.age = age;
          this.job = job;
          //方法
          if(typeof this.sayName != "function"){
              Person.prototype.sayName = function(){
                  alert(this.name);
              };
          }
      }
                      
    6. 寄生构造函数模式

      除了用new操作符并把使用的包装函数叫做构造函数外,这个方法与工厂模式是一样的

      例:具有额外方法的特殊数组,不又直接修改Array的构造函数
      function SpecialArray(){
          //创建数组
          var values = new Array();
          
          //添加值
          values.push.apply(values, arguments);
          
          //添加方法
          values.toPipedString = function(){
              return this.join("|");
          };
          
          return values;
      }
      var colors = new SpecialArray("red","blue","green");
      alert(colors.toPipedString());    
                      

      使用这种模式,建议不要与其他模式混用

    继承

    1. 通常说的继承有接口继承和实现继承,由于js无方法签名,所以不支持接口继承。只通过原型链实现了实现继承。
    2. 原型链

      实现方法:SubType.prototype = new SuperType();

      注1:子类型需要重写超类方法或添加超类中不存在的方法,需要在实现继承语句之后,这样才能屏蔽超类方法

      注2:在通过原型链实现继承时,不能使用对象字面量方法创建原型方法,因为这样做会重写原型链

    3. 借用构造函数(伪造对象/经典继承)

      在子类型构造函数的内部调用超类型构造函数SuperType.call(this);

      比原型链继承的优点是,解决了实例共享的问题,并可以传递参数

      缺点同实例相同,也具有方法不能共享的问题

    4. 组合模式
      function SuperType(name){
          this.name = name;
          this.colors = ["red","blue","green"];
      }
      SuperType.prototype.sayName = function(){
          alert(this.name);
      };
      
      function SubType(name, age){
          SuperType.call(this,name);
          
          this.age = age;
      }
      
      SubType.prototype = new SuperType();
      
      SubType.prototype.sayAge = function(){
          alert(this.age);
      };
      
      var instance1 = new SubType("Nicholas",29);
      instance1.colors.push("black");
      alert(instance1.colors);
      instance1.sayName();
      instance1.sayAge();
      
      var instance2 = new SubType("Greg",27);
      alert(instance2.colors);
      instance2.sayName();
      instance2.sayAge();
                          
    5. 原型式继承
      function object(o){
          function F(){}
          F.prototype = o;
          return new F();
      } 
                          

      实现对传入对象o的浅复制,IE9+的Object.create(o)有相似功能

  • 相关阅读:
    Deep Learning(深度学习)学习笔记整理系列五
    Deep Learning(深度学习)学习笔记整理系列四
    Deep Learning(深度学习)学习笔记整理系列三
    Deep Learning(深度学习)学习笔记整理系列二
    Deep Learning(深度学习)学习笔记整理系列 一
    java对象转为json字符串
    eclipse常用功能及快捷键
    fiddler详解
    http状态码
    eclipse中文乱码
  • 原文地址:https://www.cnblogs.com/mid-summer/p/3975380.html
Copyright © 2020-2023  润新知