zoukankan      html  css  js  c++  java
  • 面向对象的程序设计-2-创建对象

    该文为阅读高级程序设计(第三本)p144-p164的理解与总结!  接受指导与批评。

    对于我,我一直是使用字面量的方式创建对象,然而体系上的创建对象的方法却并不局限于此。

    创建对象的方法

    1. 工厂模式
    2. 构造函数模式
    3. 原型模式
    4. 组合使用构造模式和原型模式
    5. 动态原型模式
    6. 寄生构造函数模式
    7. 稳妥的构造函数模式

    1 工厂模式:

      定义工厂函数创建并返回包含特定属性的对象, 

    function createPerson(name, age, job) {
        var o = new Object();    // var o = {}; //一样
        o.name = name;
        o.age = age;
        o.job = job;
        o.sayName = function() {
            alert(this.name);
        }
        return o;
    }
    var person0 = createPerson('jody', 22, 'wife');

    2 构造函数模式:

      先贴出代码

    function Person(name) {
        this.name = name;
        this.sayName = function() {
            console.log(this);
        }
    }
    var person1 = new Person('xxx');
    var person2 = new Person('bbb');
    console.log(person1)

      2.1 new Person() 的发生了什么?步骤分解:这是重点(new的工作原理)

      1. 新建一个对象: instance = new Object(); 
      2. 设置原型链: instance.prototype = Person.prototype 
        1.   任意函数在创建的时候都会创建prototype对象,并自动为它添加constructor属性
      3. 让 Person 中的 this 指向 instance, 然后执行函数:
        1.   相当于在instance中定义属性(name,sayName)
      4. 判断 Person 函数的返回 :
        1.   Person 中没有写return,相当于return undefined(值类型),因此返回instance
        2.   如果返回值类型,则丢弃该值类型, 然后返回 instance。
        3.   如果返回引用类型,则丢弃instance, 返回该引用类型。

      2.2 构造函数也是函数,

        它是可以直接执行的,然后给执行作用域绑定属性。    

        任何函数,只要使用new 操作符,这个函数函数就变成了构造函数

      2.3 构造函数的优缺点

          1.优点:

    person1 instanceof Person
    person2 instanceof Object   //都为ture,用于判断类型(工厂模式不行)

          2.缺点:公共属性(如sayName)在每一个Person实例中都创建了,不能做到复用

    3 原型模式

    function Person() {
    };
    Person.prototype.sayName = function() {
        console.log(this.name);
    }
    Person.prototype.name = 'miaowwwwww';
    var person1 = new Person();
    var person2 = new Person();
    person1.sayName();
    console.log(person1)

      3.1 什么是原型对象??

        当创建一个函数的时候,js根据一组特定的规则自动地为函数创建 prototype 属性 和 一个原型对象。

        prototype 属性是一个指针,指向原型对象。

        原型对象自动获得一个 constructor(构造函数) 指针属性,该属性指向 被创建的函数。

      3.2 实际应用重点:

            使用构造函数创建的每一个实例,都自动包含一个[[prototype]] 指针属性。(在浏览器prototype是隐藏的,一些浏览器提供__proto__)。

            并且这个属性指向,构造函数的 prototype (即原型对象, 所以每一个实例共享一个原型对象

      3.3 构造函数-原型-实例的关系如图:

       3.4 注意:

      1.  原型对象上的可遍历属属性将会出现在 实例的 for-in 遍历中  
      2.  构造函数 Person.prototype 是一个指针
        1.   若使用 Person.prototype.sayName = function() {...}  表示在原 原型中添加属性
        2.   若使用如下方式:表示 改变了 Person.prototype 的指针, 让它指向了一个新的对象,该对象的属性被实例共享,当缺失了constructor属性
          Person.prototype = {
              constructor: Person,    // 可手动添加,补全constructor属性
              name: 'miaowwwww',
              sayName: function() {
                  console.log(this.name);
              }
          }

       3.5 原型模式的优缺点

           1.优点:

        1.   完善构造函数模式的缺点,所有实例可以共享原型的方法,而不需要是个实例创建副本,提高复用性
        2.   类型判断
    person1 instanceOf Person 
    Person.isPrototypeOf(person1)
    Object.getPrototypeOf(person1) === Person
    // 都可以正确判断结果

           2.缺点:若原型中使用引用类型,则实例可以修改原型中的

    function Person() {};
    Person.prototype = {
        constructor: Person,
        name: 'miaowwwww',
        friends: ['jody', 'robin'],
        sayName: function() {}
    }
    var person1 = new Person();
    var person2 = new Person();
    person1.friends.push('mike');
    // person2.friends : ['jody', 'robin', 'mike'];

      

     4. 组合构造函数模式与原型模式

    function Bird(name) {
        this.name = name;
        this.friends = ['mike', 'jody'];
    }
    Bird.prototype = {
        sayName: function() {
            console.log(this.name);
        }
    }

       4.1 优点: 结合构造函数模式与原型模式的优点,把引用类型的属性,放到构造函数中,为每一个实例创建副本,同时复用原型上的方法

    5.动态原型模式

    function Cat(name) {
        this.name = name;
        this.friends = ['a', 'b'],
        if(typeof this.sayName !== 'function') {
            Cat.prototype.sayName = function() {
                console.log(this.name);
            }
        }
    }

      5.1 解读:就是把第四种模式,变异一下,在判断实例没有 sayName 方法的时候才添加 该方法到 原型上

           每次新建对象的时候都会执行判断代码, 然后只有第一次执行, if 才为true

    6.寄生构造函数模式

    function Book(name) {
        var o = new Array();
        o.name = name;
        o.sayName = function() {
            console.log(this.name);
        }
        return o;
    }
    var book1 = new Book('javascript');

       6.1 请回顾上面说过的 2.1 new 的工作原理

       6.2 理解:

      1. 这种方法除了 return 以及 new Book()  之外,跟工厂函数基本没有区别。
      2. 可以理解为对已有对象的增强(如这里的Array,因为不能直接修改Array对象)

      6.3 缺点:

      1. book1 的原型中不包含 Book, 而是Array, 所以叫寄生
      2. 与构造函数一样,每一个实例都有 sayName.. 的副本,复用性降低

     7 稳妥的构造函数模式

    function Fish(_name){
        var o = new Object(); // new Person(); 或其他对象
        
        // 私有变量和函数
        var name = _name;
        function sayHi() {
            console.log('hi')
        };
        // ...
    
        // 添加方法
        o.sayName = function() {
            console.log(name);
            sayHi();
            return name;
        }
        o.setName = function(value) {
            name = value;
        }
        return o;
    }
    var aa = Fish('miaowwwww');
    var bb = Fish('jody');
    aa.sayName();
    bb.sayName();

      7.1 这个竟然是平时一直在用的闭包。

      7.2 优点:变量私有化,并且只能通过特定接口访问

        缺点: 又是每一个实例一个函数副本,复用性降低了;

      

  • 相关阅读:
    Kafka发送到分区的message是否是负载均衡的?
    SpringCloud使用Feign出现java.lang.ClassNotFoundException: org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory异常
    JDBC Mysql 驱动连接异常
    Mysql启动失败解决方案
    前段时间在微信公众号写的文章
    Java线程wait和sleep的区别
    nginx配置反向代理
    分布式锁的几种实现方式
    java四种修饰符的限制范围
    传值&传值引用
  • 原文地址:https://www.cnblogs.com/miaowwwww/p/6256130.html
Copyright © 2011-2022 走看看