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);
目录
相关文章
|
2月前
|
设计模式 JavaScript 数据安全/隐私保护
js设计模式之工厂模式
js设计模式之工厂模式
25 0
|
2月前
|
JavaScript 前端开发 Java
JavaScript语言
JavaScript语言
15 1
|
1月前
|
设计模式 前端开发 算法
【面试题】 ES6 类聊 JavaScript 设计模式之行为型模式(二)
【面试题】 ES6 类聊 JavaScript 设计模式之行为型模式(二)
|
1月前
|
前端开发 JavaScript 程序员
JavaScript高级技巧:深入探索JavaScript语言的高级特性和用法
JavaScript高级技巧:深入探索JavaScript语言的高级特性和用法
|
2月前
|
设计模式 存储 JavaScript
js设计模式之单例模式
js设计模式之单例模式
41 7
|
2月前
|
存储 JavaScript 前端开发
对象和类:JS是一种基于对象的语言,可以创建和使用自定义对象。ES6引入了类的概念,使得面向对象编程更加方便。
对象和类:JS是一种基于对象的语言,可以创建和使用自定义对象。ES6引入了类的概念,使得面向对象编程更加方便。
17 0
|
2月前
|
JavaScript 前端开发 容器
JavaScript语言
JavaScript语言
|
4月前
|
设计模式 JSON 前端开发
前端面试必看(手写Promise+js设计模式+继承+函数柯里化等)JavaScript面试全通关(1/3)
前端面试必看(手写Promise+js设计模式+继承+函数柯里化等)JavaScript面试全通关(1/3)
30 0
|
5月前
|
设计模式
js-设计模式
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
|
6月前
|
JavaScript 前端开发
网页编程和设计 JavaScript语言(ES5)(六)
网页编程和设计 JavaScript语言(ES5)(六)

相关产品

  • 云迁移中心