JavaScript设计模式(六):语言之魂-原型模式

简介: 语言之魂-原型模式

原型模式(Prototype)

用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性以及方法。

需求:创建一个焦点轮播图

<p>自动切换</p>
<img id="carousel1" class="carousel" src=""/>
<p>监听滚动切换</p>
<img id="carousel2" class="carousel" src=""/>
// 图片轮播类
var Carousel = function (imgList, container) {
   
   
    // 轮播索引
    this.index = 0;
    // 轮播图片数组
    this.imgList = imgList;
    // 轮播图片容器     
    this.container = container;
    // 创建轮播图片
    this.create = function () {
   
   
        let img = document.getElementById(this.container);
        img.src = this.imgList[this.index];
    };
    // 切换下一张图片
    this.change = function () {
   
   
        const that = this;
        setInterval(function () {
   
   
            let img = document.getElementById(that.container);
            that.index++;
            if (that.index > that.imgList.length - 1) {
   
   
                that.index = 0;
            }
            console.log(`%c【${container}】 ---> ${that.index}`, 'background-color: pink; color: black;');
            img.src = that.imgList[that.index];
        }, 2000)
    };
};

image.png

  • 默认的轮播

      let imgList = [
          'https://dummyimage.com/500x300/f00/fff&text=00',
          'https://dummyimage.com/500x300/0f0/fff&text=01',
          'https://dummyimage.com/500x300/00f/fff&text=02',
          'https://dummyimage.com/500x300/ff0/fff&text=03',
          'https://dummyimage.com/500x300/0ff/fff&text=04',
      ];
    
      // 实例化轮播图类 - 自动切换类
      let carousel = new Carousel(imgList, 'carousel1');
      carousel.create();
      carousel.change();
    
  • 重写的轮播形式 (监听滚动切换轮播)

      // 实例化轮播图类 - 上下滑动切换类
      let SlideCarousel = function (imgList, container) {
         
         
          const that = this;
          // 构造函数继承图片轮播类
          Carousel.call(that, imgList, container);
          // 重写继承的切换下一张图片方法
          that.change = function () {
         
         
              let img = document.getElementById(that.container);
              // 监听滚动
              img.addEventListener('wheel', function (e) {
         
         
                  // 向上滚动
                  if (e.wheelDelta > 0) {
         
         
                      that.index++;
                      if (that.index > that.imgList.length - 1) {
         
         
                          that.index = 0;
                      }
                  }
                  // 向下滚动 
                  else {
         
         
                      that.index--;
                      if (that.index < 0) {
         
         
                          that.index = that.imgList.length - 1;
                      }
                  }
                  console.log(`%c【${container}】 ---> ${that.index}`, 'background-color: yellow; color: black;');
                  img.src = that.imgList[that.index];
              });
          }
      };
    
      // 实例化轮播图类 - 上下滑动切换类
      let slideCarousel = new SlideCarousel(imgList, 'carousel2');
      slideCarousel.create();
      slideCarousel.change();
    
  • 缺点:
    • 属性方法 都写在基类 Carousel 的构造函数里面,那么每次子类继承都要创建一次父类,假如父类的构造函数中创建时存在很多耗时逻辑,或者每次初始化都做一些重复性工作,这样的性能消耗很大。
      • 比如: this.create = ···this.change = ··· 就属于消耗性能的逻辑

【原型模式】优化上述代码:

  • 优化:
    • 为了提高性能,我们需要有一种 共享机制 ,这样每当创建基类时,对于每次创建的一些 简单而又差异化的属性 我们可以 放在构造函数中 ,而我们将一些 消耗资源比较大的方法 放在基类的原型 中,这样就会 避免很多不必要的消耗 ,这也就是 原型模式 的一个雏形。

image.png

  • 默认的轮播

      // 图片轮播类
      var Carousel = function (imgList, container) {
         
         
          // 轮播索引
          this.index = 0;
          // 轮播图片数组
          this.imgList = imgList;
          // 轮播图片容器     
          this.container = container;
    
      };
    
      Carousel.prototype = {
         
         
          // 创建轮播图片
          create: function () {
         
         
              let img = document.getElementById(this.container);
              img.src = this.imgList[this.index];
          },
          // 切换下一张图片
          change: function () {
         
         
              const that = this;
              setInterval(function () {
         
         
                  let img = document.getElementById(that.container);
                  that.index++;
                  if (that.index > that.imgList.length - 1) {
         
         
                      that.index = 0;
                  }
                  img.src = that.imgList[that.index];
              }, 2000)
          }
      };
    
      let imgList = [
          'https://dummyimage.com/500x300/f00/fff&text=00',
          'https://dummyimage.com/500x300/0f0/fff&text=01',
          'https://dummyimage.com/500x300/00f/fff&text=02',
          'https://dummyimage.com/500x300/ff0/fff&text=03',
          'https://dummyimage.com/500x300/0ff/fff&text=04',
      ];
    
      // 实例化轮播图类 - 自动切换类
      let carousel = new Carousel(imgList, 'carousel1');
      carousel.create();
      carousel.change();
    
  • 重写的轮播形式 (监听滚动切换轮播)

      // 实例化轮播图类 - 上下滑动切换类
      let SlideCarousel = function (imgList, container) {
         
         
          // 构造函数继承图片轮播类
          Carousel.call(this, imgList, container);
      };
    
      SlideCarousel.prototype = new Carousel();
    
      // 重写继承的切换下一张图片方法
      SlideCarousel.prototype.change = function () {
         
         
          const that = this;
          let img = document.getElementById(that.container);
          // 监听滚动
          img.addEventListener('wheel', function (e) {
         
         
              // 向上滚动
              if (e.wheelDelta > 0) {
         
         
                  that.index++;
                  if (that.index > that.imgList.length - 1) {
         
         
                      that.index = 0;
                  }
              }
              // 向下滚动 
              else {
         
         
                  that.index--;
                  if (that.index < 0) {
         
         
                      that.index = that.imgList.length - 1;
                  }
              }
              img.src = that.imgList[that.index];
          });
      };
    
      // 实例化轮播图类 - 上下滑动切换类
      let slideCarousel = new SlideCarousel(imgList, 'carousel2');
      slideCarousel.create();
      slideCarousel.change();
    

原型模式的特点:

原型模式对继承他的子类都可以访问其上的属性和方法,包括杜父类拓展的方法

// 比如:

// ···Code

// 父类上拓展的方法
Carousel.prototype.getImgListCount = function () {
   
   
    console.log(this.imgList.length);
};

// 子类上拓展的方法
SlideCarousel.prototype.getContainer = function () {
   
   
    console.log(this.container);
};

// 子类访问父类上拓展的方法
slideCarousel.getImgListCount();    // 5
// 子类访问自己类上拓展的方法
slideCarousel.getContainer();       // carousel2

原型继承

比如现在没有人的基类,只有人的一些特性类,比如游泳、跑步、唱歌、跳舞等等,那么就可以通过以下方法创造出一个人的实例

function prototypeExtend(...args) {
   
   
    // 缓存类,为实例化返回对象临时创建
    const F = function () {
   
    };
    for (let i = 0; i < args.length; i++) {
   
   
        // 遍历每个模板对象中的属性
        for (let key in args[i]) {
   
   
            // 将这些属性复制到缓存类原型中
            F.prototype[key] = args[i][key];
        }
    }
    // 返回缓存类的一个实例
    return new F();
}

let Swim = function (speed) {
   
   
    this.speed = speed;
    this.swim = function () {
   
   
        console.log('游泳速度 ' + this.speed);
    };
};

let Run = function () {
   
   
    this.run = function (speed) {
   
   
        console.log('跑步速度 ' + speed);
    };
};

let Jump = function () {
   
   
    this.jump = function () {
   
   
        console.log('跳跃动作 ');
    };
};

let person = prototypeExtend(new Swim(20), new Run(), new Jump());
person.run(10);     // 跑步速度 10
person.swim();      // 跑步速度 20
/**
 * F {
 *      [[Prototype]]: {
 *          jump: ƒ (),
 *          run: ƒ (speed),
 *          speed: 20,
 *          swim: ƒ (),
 *          constructor: ƒ ()
 *          [[Prototype]]: Object
 *      }
 * }
 */
console.log(person);
目录
相关文章
|
3月前
|
前端开发 JavaScript 开发者
JavaScript:无处不在的Web语言
JavaScript:无处不在的Web语言
|
7月前
|
设计模式 JavaScript Java
【设计模式】【创建型模式】原型模式(Prototype)
一、入门 什么是原型模式? 原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过实例化类。 原型模式的核心是克隆(Clone),即通过复制现有
222 15
|
9月前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
495 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
设计模式 JavaScript 前端开发
JavaScript设计模式--访问者模式
【10月更文挑战第1天】
305 124
|
10月前
|
设计模式 JavaScript 算法
浅谈几种js设计模式
设计模式是软件开发中的宝贵工具,能够提高代码的可维护性和扩展性。通过单例模式、工厂模式、观察者模式和策略模式,我们可以解决不同场景下的实际问题,编写更加优雅和高效的代码。
306 8
|
11月前
|
设计模式 存储 Java
「全网最细 + 实战源码案例」设计模式——原型模式
原型模式(Prototype Pattern)是一种创建型设计模式,通过复制现有对象来创建新对象,适用于创建成本高或复杂的对象场景。其核心思想是“克隆”,避免直接实例化类。结构上分为抽象原型类、具体原型类和客户端。优点包括减少对象创建成本、隐藏复杂性、简化实例创建;缺点是处理循环引用的复杂对象时较为麻烦。实现步骤为定义原型类、重写`clone()`方法并调用。注意事项包括浅拷贝与深拷贝的区别及`Cloneable`接口的使用。
191 20
|
设计模式 前端开发 JavaScript
JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式
本文深入探讨了JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式,结合电商网站案例,展示了设计模式如何提升代码的可维护性、扩展性和可读性,强调了其在前端开发中的重要性。
181 2
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
345 4
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
XML 监控 JavaScript
JavaScript 语言对企业上网监控的技术支持
在数字化企业环境中,上网监控对企业信息安全和提升员工效率至关重要。JavaScript 作为广泛应用的脚本语言,提供了强大的技术支持,包括数据获取与分析、与服务器端交互、监控页面加载时间和网络活动,助力企业有效管理上网行为,保障信息安全。
122 6