前端设计模式之原型模式

217 阅读2分钟

原型模式

概念: 原型模式就是将可复用的、可共享的、耗时巨大的从基类中提取出来然后放在其原型当中,然后子类通过组合集成或者寄生组合挤成而将方法和属性集成下来,然后对子类中对应的需要重写的方法进行重写,这样子类创建的对象既具有子类的属性和方法也共享了基类的原型方法。

实例

function LoopImages(imgs, container) {
    this.images = imgs
    this.container = container
}
LoopImages.prototype = {
    createImage: function() {
        console.log('LoopImages createImage function')
    },
    changeImage: function() {
        console.log('LoopImages changeImage function')
    }
}
// 上下滑动切换类
function SlideLoopImages(imgs, container, arrow) {
    LoopImages.call(this, imgs, container)
    this.arrow = arrow
}
SlideLoopImages.prototype = {
    ...new LoopImages().__proto__,
    constructor: SlideLoopImages,
    createImage:function(){
        console.log('SlideLoopImages createImage function')
    }
}
/**
 * 上面代码偷了个懒,这里使用了es6的扩展运算符,将基类原型属性直接扩展到
 * 了子类的原型链上面,这里要如何使用,请根据自己的实际情况操作,当所谓基类
 * 也是某个类的子类的时候,上面方法便不能很好的继承祖先的原型属性了。一定
 * 要注意。
 */
 
// 渐隐切换类
function FadeLoopImages(imgs, container) {
    LoopImages.call(this, imgs, container)
}
FadeLoopImages.prototype = new LoopImages()
FadeLoopImages.prototype.construtor = FadeLoopImages
FadeLoopImages.prototype.changeImage = function() {
    console.log('FadeLoopImages changeImage function')
}
/**
 * 上面的代码使用了组合继承的方式去实现继承,组合继承的方式可以讲原型链完整
 * 的继承下来,但是同样也需要注意原型链将基类实例属性保存两份在子类的缺点。
 */

 // 看一下输出结果
const slideLoopImages = new SlideLoopImages([1,2,4], '#slide', 'top')
const fadeLoopImages = new FadeLoopImages([3,5,6], '#fade')
slideLoopImages.createImage() // SlideLoopImages createImage function
slideLoopImages.changeImage() //LoopImages changeImage function
console.log('---------------')
fadeLoopImages.createImage() // LoopImages createImage function
fadeLoopImages.changeImage() // FadeLoopImages changeImage function

扩展:

上面的代码当中,我们使用了call方法,来改变基类构造方法的作用域,那么让我们来顺便看一下改变方法作用对象的几个方法及其区别吧,即bind、call、apply的作用及区别

  1. 对比
    name 参数 返回值 作用
    bind n个 函数 另一个对象替换方法的当前对象
    call n个 函数执行结果 另一个对象替换方法的当前对象
    apply 2个 函数执行结果 另一个对象替换方法的当前对象
  2. 参数解释:
    bind、call、apply三个方法的第一个参数都是目标对象,用目标对象替换方法的当前对象;
    bind、call都接受n个参数,其中第一个参数作用如上面所述,自第二个参数起的后续参数表示该调用方法的参数;
    apply方法只接受两个参数,第一个参数如上所述,而第二个参数是一个又方法参数装载成的数组。
  3. 手撸一个bind
    注意: bind是在es5当中扩展的方法,在ie6、7、8当中并不能够使用,那么下面来玩玩如何手写一个bind。
```
if (!Function.prototype.bind) {
    Function.prototype.bind = function (context) {
        var self = this;
        var args = [].slice.call(arguments);
        return function () {
            self.apply(context, args.slice(1));
        }
    }
}
```

github地址:github.com/ypf0088/blo…