参与者模式: 在特定的作用域中执行给定的函数。并将参数原封不动的传递
需求情景: 定时从后端拉取数据,缓存下来,一旦用户点击查看,就要展示这些信息
=》 点击一个按钮要将额外的数据传入这个事件的回调函数中
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>