访问者模式(Visitor)
针对于对象结构中的元素,定义在不改变该对象的前提下访问结构中元素的新方法。
解决this
指向在IE
下指向window
的问题:
错误示例:(
IE8及以下this指向window
)/** * 绑定事件 * @param {HTMLElement} el DOM元素 * @param {string} type 事件类型 * @param {Function} fn 时间函数 */ function bindEvent(el, type, fn) { if (el.addEventListener) { el.addEventListener(type, fn, false); } else if (el.attachEvent) { el.attachEvent('on' + type, fn); } else { el['on' + type] = fn; } } var text = document.getElementById('text'); bindEvent(text, 'click', function () { // 非IE下: HTMLElement false // IE8及以下: [object Window] true console.log(this, this === window); this.style.backgroundColor = 'red'; // IE8及以下报错 });
解决
IE8及以下
报错问题:/** * 绑定事件 * @param {HTMLElement} el DOM元素 * @param {string} type 事件类型 * @param {Function} fn 时间函数 */ function bindEvent(el, type, fn) { if (el.addEventListener) { el.addEventListener(type, fn, false); } else if (el.attachEvent) { // 解决IE8及以下报错问题 el.attachEvent('on' + type, function (e) { fn.call(el, e); // 修改了回调函数的指向 }); } else { el['on' + type] = fn; } } var text = document.getElementById('text'); bindEvent(text, 'click', function () { console.log(this); // 指向了HTMLElement this.style.backgroundColor = 'red'; });
为对象变量添加类似数组的方法
- 数组操作方法(
pop
splice
push
):let b = []; b.name = 'Lee'; b.age = 18; console.log(b.push(1, 2, 3, 4)); // 4 console.log(b); // [1, 2, 3, 4, name: 'Lee', age: 18] ---> length: 4 console.log(b.splice(1, 2)); // (2) [2, 3] console.log(b); // (2) [1, 4, name: 'Lee', age: 18] ---> length: 2 console.log(b.pop()); // 4 console.log(b); // [1, name: 'Lee', age: 18] ---> length: 1
利用访问者模式实现对象变量访问数组上自带的事件方法:
// 访问器 var Visitor = (function () { return { // 追加数据方法 push(...args) { // 对第一个参数对象执行push方法 return Array.prototype.push.apply(args[0], args.slice(1)); }, // 截取方法 splice(...args) { // 对第一个参数对象执行splice方法 return Array.prototype.splice.apply(args[0], args.slice(1)); }, // 弹出最后一次添加的元素 pop(...args) { // 对第一个参数对象执行pop方法 return Array.prototype.pop.apply(args[0]); } } })(); let a = { name: 'Lee', age: 18 }; console.log(Visitor.push(a, 1, 2, 3, 4)); // 4 console.log(a); // {0: 1, 1: 2, 2: 3, 3: 4, name: 'Lee', age: 18, length: 4} console.log(Visitor.splice(a, 1, 2)); // (2) [2, 3] console.log(a); // {0: 1, 1: 4, name: 'Lee', age: 18, length: 2} console.log(Visitor.pop(a)); // 4 console.log(a); // {0: 1, name: 'Lee', age: 18, length: 1}
特点:
访问者更适合于那些数据稳定,但是数据的操作方法
易变的环境
下。因此当操作环境改变
时,可以
自由修改操作方法以适应操作环境
,而不用修改原数据
,实现操作方法的拓展
。同时对于同一个数据,它可以被多个访问对象所访问,这
极大增加了操作数据的灵活性
。
访问者模式
指在不同的环境下
都可以从容的进行事件调用及访问,以及使用对象去访问数组可以直接访问的方法。