JS设计模式: 参与者模式

参与者模式: 在特定的作用域中执行给定的函数。并将参数原封不动的传递

需求情景: 定时从后端拉取数据,缓存下来,一旦用户点击查看,就要展示这些信息

=》 点击一个按钮要将额外的数据传入这个事件的回调函数中

let A = { event: {} }

A.event.on = function(dom, type, fn) {
    if(dom.addEventListener) {
        dom.addEventListener(type, fn, false)
    }else if(dom.attachEvent) {
        dom.attachEvent('on' + type, fn)
    }else{
        dom['on'+ type] = fn 
    }
}


// 难点 addEventListener 不能传入data
// 解决 在回调函数里面做文章

A.event.on = function(dom, type, fn, data) {
    if(dom.addEventListener) {
        dom.addEventListener(type, function(e){
            fn.call(dom, e, data)
        })
    }
}

// 新问题: 添加的事件回调函数不能移除了
// 解决: bind apply改变this  apply 小demo


function bind(fn, context) {
    return function() {
        return fn.apply(context, arguments)
    }
}

var demoObj = {
    title: '这是一个demo',
}
function demoFn() {
    console.log(this.title)
}
var bindFn = bind(demoFn, demoObj)

bindFn() // 这是一个例子



var btn = document.getElementsByTagName('button')[0];

var p = document.getElementsByTagName('p')[0]

//改造
function demoFn() {
    console.log(arguments, this)
}

var bindFn = bind(demoFn)

btn.addEventListener('click', bindFn)    // [MouseEvent] Window {external: Object, chrome: Object, document: document, demoObj: Object, btn: button…}

bindFn = bind(demoFn, btn)

btn.addEventListener('click', bindFn)    // [MouseEvent] <button>​click me​</button>​


// 有些高级浏览器有提供bind函数 实现如下

var bindFn = demoFn.bind(demoObj)

/**
 * 函数柯里化: 对函数的参数分割, 类似于多态
 */

function curry(fn) {
    //缓存数据slice方法

    var slice = [].slice

    var args = slice.call(arguments, 1);

    return function() {
        var addArgs = slice.call(arguments),
            allArgs = args.concat(addArgs)

        return fn.apply(null, allArgs)
    }
}

function add(num1, num2) {
    return num1 + num2
}
function add5(num) {
    return 5+num
}

//用curry实现两种加法 函数的创建过程在curry里实现了
let add7= curry(add, 7, 8)
let add58 = curry(add, 5)


//重写bind
function bind(fn, context) {
    var slice = Array.prototype.slice,
    args = slice.call(arguments, 2)

    return function() {
        var addArgs = slice.call(arguments),
            allArgs = addArgs.concat(args);

        return fn.apply(context, allArgs)
    }
}


// 测试

var demoData1 = {
        text: '这是第一组数据'
    },
    demoData2 = {
        text: '第二个数据'
    }

bindFn = bind(demoFn, btn, demoData1) 

btn.addEventListener('click', bindFn)    // [MouseEvent, Object<demoData1>]  <button>​click me​</button>​
发布了13 篇原创文章 · 获赞 12 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Forever201295/article/details/104032369